1 options & settings

1.1 chunk options

CSS for scrollable output & Header colors

Turning scientific / Exponential numbers off

options(scipen = 999)

1.2 Loading libs

library(tidyverse)
library(ggthemes)
library(lubridate)
library(covid19.analytics)
library(data.table)
library(plotly)
library(gghighlight)
library(zoo)   # this is for moving averages
# library(ggThemeAssist) 
library(glue)
library(scales)
library(ggtext)
library(patchwork)
library(ggforce)

1.3 Creating & setting custom theme


theme_viny_bright <- function(){
  
  library(ggthemes)
  
  ggthemes::theme_fivethirtyeight() %+replace%
  
  theme(
    axis.title = element_text(),
    axis.text = element_text(size = 13),
    legend.text = element_text(size = 10),
    panel.background = element_rect(fill = "white"),
    plot.background = element_rect(fill = "white"),
    strip.background = element_blank(),
    legend.background = element_rect(fill = NA),
    legend.key = element_rect(fill = NA),
    plot.title = element_text(hjust = 0.5, size = 14, face = "plain",
                              family = "serif"),
    plot.subtitle = element_text(hjust = 0.5,face = "plain", family = "serif", size = 9),
    plot.caption = element_text(hjust = 1, colour = "maroon", size = 8)
      )
  }

theme_set(theme_viny_bright())

2 Dual axis plot

2.1 Lineplt: Dailycases Vs Dailydeaths

2.1.1 Data Prep.

grouped_cases_df %>% head()
scaleFactor = max(grouped_cases_df %>% 
                    filter(Country.Region == "India") %>% 
                    pull(Daily_cases)) / 
              max(grouped_cases_df %>% 
                    filter(Country.Region == "India") %>% 
                    pull(Daily_deaths))

scaleFactor

2.1.2 Basic dual axis plot

ggplot(data = (grouped_cases_df %>% filter(Country.Region == "India")),
       aes(x = Date)) +
  geom_line(aes(y = Daily_cases), col = "blue") +
  geom_line(aes(y = Daily_deaths * scaleFactor), col = "red") +
  scale_y_continuous(name = "Daily Cases", sec.axis = sec_axis(~./scaleFactor, name = "Daily Deaths")) +
  
  theme(
    axis.title.y.left=element_text(color="blue"),
    axis.text.y.left=element_text(color="blue"),
    axis.title.y.right=element_text(color="red"),
    axis.text.y.right=element_text(color="red")
  )

2.1.3 Function1 dual axis plot

this function supports passing of Country.Region names without using quotes but it creates problems for countries that have space in name.

fn_Comapare_confrm_to_deaths <- function(Country_selected = India) {
  Country_selected_enquo = enquo(Country_selected)
  
  daily_col = "#32a4ba"
  death_col = "#f08080"

grouped_cases_df %>%
          filter(Country.Region == quo_name(Country_selected_enquo)) %>%

ggplot(aes(x = Date)) +
  geom_line(aes(y = Daily_cases), col = daily_col, size = 0.8) +
  geom_line(aes(y = Daily_deaths * scaleFactor), col = death_col, size = 0.8, 
            size = 0.8, alpha = 0.8) +
  scale_y_continuous(name = "Daily Cases", sec.axis = sec_axis(~./scaleFactor, name = "Daily Deaths"),
                     labels = scales::comma_format()) +
  scale_x_date(date_breaks = "1 month", date_labels = "%b") +
  
  theme_excel_new() +

  theme(
    axis.title.y.left=element_text(color=daily_col),
    axis.text.y.left=element_text(color=daily_col),
    axis.title.y.right=element_text(color=death_col),
    axis.text.y.right=element_text(color=death_col),
    plot.title = element_text(face = "plain", family = "serif", size = 14)
  ) + 
  
  theme(plot.title = element_markdown() ) +
  
  labs(title = glue("<i>{quo_name(enquo(Country_selected))}</i>: Daily confirmed & death cases"),
       caption = "created by ViSa (SciArt!!)") +
  coord_fixed(ratio = .0028)
}

fn_Comapare_confrm_to_deaths(Germany)

2.1.4 Function2 dual axis plot

this function requires passing of Country.Region names within quotes only support country names that have space in it.

fn_Comapare_confrm_to_deaths <- function(Country_selected = "India") {
  # Country_selected_enquo = enquo(Country_selected)
  
  daily_col = "#32a4ba"
  death_col = "#f08080"

grouped_cases_df %>%
          filter(Country.Region == Country_selected) %>%

ggplot(aes(x = Date)) +
  geom_line(aes(y = Daily_cases), col = daily_col, size = 0.8) +
  geom_line(aes(y = Daily_deaths * scaleFactor), col = death_col, 
            size = 0.8, alpha = 0.8) +
  scale_y_continuous(name = "Daily Cases", sec.axis = sec_axis(~./scaleFactor, name = "Daily Deaths"),
                     labels = scales::comma_format()) +
  scale_x_date(date_breaks = "1 month", date_labels = "%b") +
  
  theme_excel_new() +
  theme(
    axis.title.y.left=element_text(color=daily_col),
    axis.text.y.left=element_text(color=daily_col),
    axis.title.y.right=element_text(color=death_col),
    axis.text.y.right=element_text(color=death_col),
    plot.title = element_text(face = "plain", family = "serif", size = 14)
  ) + 
  theme(plot.title = element_markdown()) +
  labs(title = glue("<i>{Country_selected}</i>: Daily confirmed & death cases"),
       caption = "created by ViSa (SciArt!!)") +
    
  coord_fixed(ratio = .0028)
  # coord_fixed(ratio = .008) 
}

plt1 <- fn_Comapare_confrm_to_deaths("United Kingdom")
plt1

2.1.5 plotly

ggplotly(fn_Comapare_confrm_to_deaths("United Kingdom"))

2.1.6 CFR level plt


fn_CFR <- function(Country_selected = "India") {
  grouped_cases_df %>% 
    filter(Country.Region == Country_selected) %>% 
    
    ggplot(aes(x = Date, y = Case_Fatality_Ratio, col = CFR_level, group = 1)) +
    geom_line(size = 0.8) +
    scale_y_continuous(labels = label_dollar(prefix = "", suffix = "%")) +
    scale_x_date(date_breaks = "1 month", date_labels = "%b") +
    theme_excel_new() +
    theme(legend.position = "bottom",
          plot.title = element_text(face = "plain", family = "serif", size = 14)) +
    
    theme(plot.title = element_markdown()) +
    labs(title = glue("<i>{Country_selected}</i>: Case Fatality Ratio(%) & level"),
         y = "CFR(%)",
         caption = "created by ViSa (SciArt!!)") +
    # ylab(label = "CFR (%)")
      
    coord_fixed(ratio = 4) 
}
  
plt2 <- fn_CFR("United Kingdom")
plt2

2.1.7 Patched Plots


plt1 / plt2

ggsave(filename = "UK_Dailycases.png", dpi = 300)

2.2 Colplt: Dailycases Vs Dailydeaths

2.2.1 Basic dual axis plot

ggplot(data = (grouped_cases_df %>% filter(Country.Region == "India")),
       aes(x = Date)) +
  geom_col(aes(y = Daily_cases), col = "blue") +
  geom_line(aes(y = Daily_deaths * scaleFactor), col = "red") +
  scale_y_continuous(name = "Daily Cases", sec.axis = sec_axis(~./scaleFactor, name = "Daily Deaths")) +
  
  theme(
    axis.title.y.left=element_text(color="blue"),
    axis.text.y.left=element_text(color="blue"),
    axis.title.y.right=element_text(color="red"),
    axis.text.y.right=element_text(color="red")
  )

2.2.2 Function1 dual axis plot

this function supports passing of Country.Region names without using quotes but it creates problems for countries that have space in name.

fn_Comapare_confrm_to_deaths <- function(Country_selected = India) {
  Country_selected_enquo = enquo(Country_selected)
  
  daily_col = "#32a4ba"
  death_col = "#f08080"

grouped_cases_df %>%
          filter(Country.Region == quo_name(Country_selected_enquo)) %>%

ggplot(aes(x = Date)) +
  geom_col(aes(y = Daily_cases), fill = daily_col, size = 0.8) +
  geom_line(aes(y = Daily_deaths * scaleFactor), col = death_col, size = 0.8, 
            size = 0.8, alpha = 0.8) +
  scale_y_continuous(name = "Daily Cases", sec.axis = sec_axis(~./scaleFactor, name = "Daily Deaths"),
                     labels = scales::comma_format()) +
  scale_x_date(date_breaks = "1 month", date_labels = "%b") +
  
  theme_excel_new() +

  theme(
    axis.title.y.left=element_text(color=daily_col),
    axis.text.y.left=element_text(color=daily_col),
    axis.title.y.right=element_text(color=death_col),
    axis.text.y.right=element_text(color=death_col),
    plot.title = element_text(face = "plain", family = "serif", size = 14)
  ) + 
  
  theme(plot.title = element_markdown() ) +
  
  labs(title = glue("<i>{quo_name(enquo(Country_selected))}</i>: Daily confirmed & death cases"),
       caption = "created by ViSa (SciArt!!)") +
  coord_fixed(ratio = .0028)
}

fn_Comapare_confrm_to_deaths(Germany)

2.2.3 Function2 dual axis plot

this function requires passing of Country.Region names within quotes only support country names that have space in it.

fn_Comapare_confrm_to_deaths <- function(Country_selected = "India") {
  # Country_selected_enquo = enquo(Country_selected)
  
  daily_col = "#32a4ba"
  death_col = "#f08080"

grouped_cases_df %>%
          filter(Country.Region == Country_selected) %>%

ggplot(aes(x = Date)) +
  geom_col(aes(y = Daily_cases), fill = daily_col, size = 0.8) +
  geom_line(aes(y = Daily_deaths * scaleFactor), col = death_col, 
            size = 0.8, alpha = 0.8) +
  scale_y_continuous(name = "Daily Cases", sec.axis = sec_axis(~./scaleFactor, name = "Daily Deaths"),
                     labels = scales::comma_format()) +
  scale_x_date(date_breaks = "1 month", date_labels = "%b") +
  
  theme_excel_new() +
  theme(
    axis.title.y.left=element_text(color=daily_col),
    axis.text.y.left=element_text(color=daily_col),
    axis.title.y.right=element_text(color=death_col),
    axis.text.y.right=element_text(color=death_col),
    plot.title = element_text(face = "plain", family = "serif", size = 14)
  ) + 
  theme(plot.title = element_markdown()) +
  labs(title = glue("<i>{Country_selected}</i>: Daily confirmed & death cases"),
       caption = "created by ViSa (SciArt!!)") +
    
  coord_fixed(ratio = .0028) 
}

plt1 <- fn_Comapare_confrm_to_deaths("United Kingdom")
plt1

2.2.4 plotly

ggplotly(fn_Comapare_confrm_to_deaths("United Kingdom"))

2.2.5 CFR level plt


fn_CFR <- function(Country_selected = "India") {
  grouped_cases_df %>% 
    filter(Country.Region == Country_selected) %>% 
    
    ggplot(aes(x = Date, y = Case_Fatality_Ratio, col = CFR_level, group = 1)) +
    geom_line(size = 0.8) +
    scale_y_continuous(labels = label_dollar(prefix = "", suffix = "%")) +
    scale_x_date(date_breaks = "1 month", date_labels = "%b") +
    theme_excel_new() +
    theme(legend.position = "bottom",
          plot.title = element_text(face = "plain", family = "serif", size = 14)) +
    
    theme(plot.title = element_markdown()) +
    labs(title = glue("<i>{Country_selected}</i>: Case Fatality Ratio(%) & level"),
         y = "CFR(%)",
         caption = "created by ViSa (SciArt!!)") +
    # ylab(label = "CFR (%)")
      
    coord_fixed(ratio = 4) 
}
  
plt2 <- fn_CFR("United Kingdom")
plt2

2.2.6 Patched Plots


plt1 / plt2

3 Latest Week plots

3.1 Top 10 in 7 days

3.1.1 facet by Date


df_stack %>% 
  filter(str_starts(df_stack$Cases_type, pattern = "Daily_"),
                    Date > (max(Date, na.rm = TRUE) - 8) & Date < max(Date, na.rm = TRUE)) %>% 
  group_by(Country.Region, Date, Cases_type) %>% 
  summarise(Cases_count = sum(Cases_count)) %>%
  group_by(Date, Cases_type) %>% 
  slice_max(order_by = Cases_count, n = 5) %>% 
  mutate(Cases_size = Cases_count / sum(Cases_count)) %>% 
  ungroup() %>% 
  
  ggplot(aes(x = Cases_type, y = Country.Region)) +
  geom_point(shape = 21, aes(size = Cases_size, color = Cases_type), fill="#f8f2e4", stroke=3) +
  # theme_minimal() +
  theme_wsj() +
  theme(axis.text.x = element_text(angle = 90),
        axis.text = element_text(size = 8),
        legend.position = "none",
        plot.title = element_text(face = "bold", family = "serif", size = 20),
        plot.subtitle = element_text(face = "plain", family = "serif", size = 12),
        plot.caption = element_text(face = "plain", family = "serif", size = 9)) +
  scale_color_tableau(palette = "Tableau 10") +
  # scale_color_wsj(palette = "colors6") +
  
  facet_wrap(~Date) +
  labs(title = "Top 5 Countries for all type of Daily cases",
       subtitle = "For Latest 7 days (Size based on each category count for same date)",
       caption = "created by ViSa (SciArt!!)") +
  coord_cartesian(clip = "off")

3.1.2 +ggtext colr axis

ref: https://wilkelab.org/ggtext/

solution from: https://stackoverflow.com/questions/65652600/how-to-use-ggtext-to-color-axis-data-labels-in-r/65652801#65652801


color = c(Daily_cases = "#2596be", Daily_deaths = "#f28e2b", Daily_recovered = "#e15759")

df_stack %>% 
  filter(str_starts(df_stack$Cases_type, pattern = "Daily_"),
                    Date > (max(Date, na.rm = TRUE) - 8) & Date < max(Date, na.rm = TRUE)) %>% 
  group_by(Country.Region, Date, Cases_type) %>% 
  summarise(Cases_count = sum(Cases_count)) %>%
  group_by(Date, Cases_type) %>% 
  slice_max(order_by = Cases_count, n = 5) %>% 
  mutate(Cases_size = Cases_count / sum(Cases_count)) %>% 
  ungroup() %>% 
  # mutate(Cases_type = glue("<i style='color:{color}'>{Cases_type}</i>")) %>% 
  mutate(Cases_type = glue("<i style='color: {color[Cases_type]}'>{Cases_type}</i>")) %>% 

  ggplot(aes(x = Cases_type, y = Country.Region)) +
  geom_point(shape = 21, aes(size = Cases_size, color = Cases_type), fill="#f8f2e4", stroke=3) +
  #theme_minimal() +
  theme_wsj() +
  theme(axis.text.x = element_text(angle = 90),
        axis.text = element_text(size = 8),
        legend.position = "none",
        plot.title = element_text(face = "bold", family = "serif", size = 20),
        plot.subtitle = element_text(face = "plain", family = "serif", size = 12),
        plot.caption = element_text(face = "plain", family = "serif", size = 9)) +
  theme(axis.text.x = element_markdown()) +
  scale_color_manual(values = c("#2596be", "#e15759", "#f28e2b")) +
  # scale_color_tableau(palette = "Tableau 10") +
  # scale_color_wsj(palette = "colors6") +
  facet_wrap(~Date) +
  labs(title = "Top 5 Countries for all type of Daily cases",
       subtitle = "For Latest 7 days separated by each date",
       caption = "created by ViSa (SciArt!!)") +
  coord_cartesian(clip = "off")

3.1.3 working solution


color = c(Daily_cases = "#2596be", Daily_deaths = "#e15759", Daily_recovered = "#f28e2b")

read.csv("https://raw.githubusercontent.com/johnsnow09/covid19-df_stack-code/main/df_stack_limited.csv") %>%
  mutate(Cases_type = glue("<i style='color: {color[Cases_type]}'>{Cases_type}</i>")) %>% 

  ggplot(aes(x = Cases_type, y = Country.Region)) +
  geom_point(shape = 21, aes(size = Cases_size, color = Cases_type), fill="#f8f2e4", stroke=3) +
  #theme_minimal() +
  theme_wsj() +
  theme(axis.text.x = element_text(angle = 90),
        axis.text = element_text(size = 8),
        legend.position = "none",
        plot.title = element_text(face = "bold", family = "serif", size = 20),
        plot.subtitle = element_text(face = "plain", family = "serif", size = 12),
        plot.caption = element_text(face = "plain", family = "serif", size = 9)) +
  theme(axis.text.x = element_markdown()) +
  scale_color_manual(values = c("#2596be", "#e15759", "#f28e2b")) +
  # scale_color_tableau(palette = "Tableau 10") +
  # scale_color_wsj(palette = "colors6") +
  facet_wrap(~Date) +
  labs(title = "Top 5 Countries for all type of Daily cases",
       subtitle = "For Latest 7 days (Size based on each category count for same date)",
       caption = "created by ViSa (SciArt!!)") +
  coord_cartesian(clip = "off")

3.1.4 facet by Cases_type


df_stack %>% 
  filter(str_starts(df_stack$Cases_type, pattern = "Daily_"),
         Date > (max(Date, na.rm = TRUE) - 8) & Date < max(Date, na.rm = TRUE)) %>% 
  group_by(Country.Region, Date, Cases_type) %>% 
  summarise(Cases_count = sum(Cases_count)) %>%
  group_by(Date, Cases_type) %>% 
  slice_max(order_by = Cases_count, n = 5) %>% 
  mutate(Cases_size = Cases_count / sum(Cases_count)) %>% 
  ungroup() %>% 
  
  ggplot(aes(x = Date, y = Country.Region)) +
  geom_point(shape = 21, aes(size = Cases_size, color = Date), fill="#f8f2e4", stroke=3) +
  # theme_minimal() +
  theme_wsj() +
  theme(axis.text.x = element_text(angle = 90),
        axis.text = element_text(size = 8),
        legend.position = "none",
        plot.title = element_text(face = "bold", family = "serif", size = 20),
        plot.subtitle = element_text(face = "plain", family = "serif", size = 12),
        plot.caption = element_text(face = "plain", family = "serif", size = 9)) +
  # scale_color_tableau(palette = "Tableau 20") +
  
  facet_wrap(~Cases_type) +
  labs(title = "Top 5 Countries for all type of Daily cases",
       subtitle = "For Latest 7 days separated by Cases Type",
       caption = "created by ViSa (SciArt!!)") +
  coord_cartesian(clip = "off")

3.2 Top5 Barplots of Cases

3.2.1 +Barplt (Daily_cases)


df_stack %>% 
  filter(Cases_type == "Daily_cases",
         Date > (max(Date, na.rm = TRUE) - 8) & Date < max(Date, na.rm = TRUE)) %>% 
  group_by(Country.Region, Date, Cases_type) %>% 
  summarise(Cases_count = sum(Cases_count)) %>%
  group_by(Date, Cases_type) %>% 
  slice_max(order_by = Cases_count, n = 5) %>% 
  mutate(Cases_size = Cases_count / sum(Cases_count)) %>% 
  ungroup() %>% 
  
  mutate(Country.Region = fct_reorder(Country.Region, Cases_count, max)) %>% 
  
  ggplot(aes(x = Cases_count, y = Country.Region)) +
  geom_col(aes(fill = Country.Region)) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 90),
        legend.position = "none",
        plot.title = element_text(face = "plain", family = "serif", size = 14),
        plot.subtitle = element_text(face = "plain", family = "serif", size = 9)) +
  scale_fill_tableau(palette = "Tableau 20") +
  scale_x_continuous(labels = scales::unit_format(scale = 1e-3, unit = "k")) +
  
  facet_wrap(~Date) +
  labs(title = "Top 5 Countries by Daily cases",
       subtitle = "For Latest 7 days separated by Dates",
       caption = "created by ViSa (SciArt!!)",
       x = "Daily Cases count",
       y = "") +
  coord_cartesian(clip = "off")

3.2.2 +Barplt (Daily_recovered)


df_stack %>% 
  filter(Cases_type == "Daily_recovered",
         Date > (max(Date, na.rm = TRUE) - 8) & Date < max(Date, na.rm = TRUE)) %>% 
  group_by(Country.Region, Date, Cases_type) %>% 
  summarise(Cases_count = sum(Cases_count)) %>%
  group_by(Date, Cases_type) %>% 
  slice_max(order_by = Cases_count, n = 5) %>% 
  mutate(Cases_size = Cases_count / sum(Cases_count)) %>% 
  ungroup() %>% 
  
  mutate(Country.Region = fct_reorder(Country.Region, Cases_count, max)) %>% 
  
  ggplot(aes(x = Cases_count, y = Country.Region)) +
  geom_col(aes(fill = Country.Region)) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 90),
        legend.position = "none",
        plot.title = element_text(face = "plain", family = "serif", size = 14),
        plot.subtitle = element_text(face = "plain", family = "serif", size = 9),
        plot.background = element_rect(colour = "black", size = 1) ) +
  scale_fill_tableau(palette = "Tableau 20") +
  scale_x_continuous(labels = scales::unit_format(scale = 1e-3, unit = "k")) +
  
  facet_wrap(~Date) +
  labs(title = "Top 5 Countries by Daily Recovered cases",
       subtitle = "For Latest 7 days separated by Dates",
       caption = "created by ViSa (SciArt!!)",
       x = "Daily Recovered Cases count",
       y = "") +
  coord_cartesian(clip = "off")

3.2.3 +Barplt (Daily_deaths)


df_stack %>% 
  filter(Cases_type == "Daily_deaths",
         Date > (max(Date, na.rm = TRUE) - 8) & Date < max(Date, na.rm = TRUE)) %>% 
  group_by(Country.Region, Date, Cases_type) %>% 
  summarise(Cases_count = sum(Cases_count)) %>%
  group_by(Date, Cases_type) %>% 
  slice_max(order_by = Cases_count, n = 5) %>% 
  mutate(Cases_size = Cases_count / sum(Cases_count)) %>% 
  ungroup() %>% 
  
  mutate(Country.Region = fct_reorder(Country.Region, Cases_count, max)) %>% 
  
  ggplot(aes(x = Cases_count, y = Country.Region)) +
  geom_col(aes(fill = Country.Region)) +
  # theme_minimal() +
  theme_clean() +
  theme(axis.text.x = element_text(angle = 90),
        legend.position = "none",
        plot.title = element_text(face = "plain", family = "serif", size = 14),
        plot.subtitle = element_text(face = "plain", family = "serif", size = 9)) +
  scale_fill_tableau(palette = "Tableau 20") +
  scale_x_continuous(labels = scales::unit_format(scale = 1e-3, unit = "k")) +
  
  facet_wrap(~Date) +
  labs(title = "Top 5 Countries by Daily Deaths",
       subtitle = "For Latest 7 days",
       caption = "created by ViSa (SciArt!!)",
       x = "Daily Death Cases count",
       y = "") +
  coord_cartesian(clip = "off")

3.2.4 plotly +subtitle


ggplotly(df_stack %>% 
  filter(Cases_type == "Daily_deaths",
         Date > (max(Date, na.rm = TRUE) - 8) & Date < max(Date, na.rm = TRUE)) %>% 
  group_by(Country.Region, Date, Cases_type) %>% 
  summarise(Cases_count = sum(Cases_count)) %>%
  group_by(Date, Cases_type) %>% 
  slice_max(order_by = Cases_count, n = 5) %>% 
  mutate(Cases_size = Cases_count / sum(Cases_count)) %>% 
  ungroup() %>% 
  
  mutate(Country.Region = fct_reorder(Country.Region, Cases_count, max)) %>% 
  
  ggplot(aes(x = Cases_count, y = Country.Region)) +
  geom_col(aes(fill = Country.Region)) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 90),
        legend.position = "none",
        plot.title = element_text(face = "plain", family = "serif", size = 14),
        plot.subtitle = element_text(face = "plain", family = "serif", size = 9)) +
  scale_fill_tableau(palette = "Tableau 20") +
  scale_x_continuous(labels = scales::unit_format(scale = 1e-3, unit = "k")) +
  
  facet_wrap(~Date) +
  labs(title = "Top 5 Countries of Daily Deaths cases",
       subtitle = "For Latest 7 days separated by Dates",
       caption = "created by ViSa (SciArt!!)",
       x = "Daily Death Cases count",
       y = "") +
  coord_cartesian(clip = "off") 
) %>%
  layout(title = list(text = paste0('Top 5 Countries of Daily Deaths cases',
                                    '<br>',
                                    '<sup>',
                                    'For Latest 7 days separated by Dates',
                                    '</sup>')))

4 Cases Distribution by continent

4.1 Latest Confirmed Cases

grouped_cases_df %>% 
  filter(Date == max(Date, na.rm = TRUE)#,
         # Confirmed < 5000000
         ) %>% 
  
  ggplot(aes(x = continent, y = log(Confirmed), label = Country.Region)) +
  geom_jitter(size = 1.8, width = 0.35, aes(shape = CFR_level, color = CFR_level)) +
  geom_violin(alpha = .5, color = 'grey50', draw_quantiles = c(.25, .5, .75)) +
  labs(title = "Latest Confirmend cases across continents",
       subtitle = "Colored by CFR severity level",
       caption = "created by ViSa (SciArt!!)")

4.2 +plotly


ggplotly(grouped_cases_df %>% 
  filter(Date == max(Date, na.rm = TRUE)#,
         # Confirmed < 5000000
         ) %>% 
  
  ggplot(aes(x = continent, y = log(Confirmed), label = Country.Region)) +
  geom_jitter(size = 1.8, width = 0.35, aes(shape = CFR_level, color = CFR_level)) +
  geom_violin(alpha = .5, color = 'grey50', draw_quantiles = c(.25, .5, .75)) +
  labs(title = "Latest Confirmend cases across continents",
       subtitle = "Colored by CFR severity level",
       caption = "created by ViSa (SciArt!!)")
)

4.3 Latest Active Cases

grouped_cases_df %>% 
  filter(Date == max(Date, na.rm = TRUE)#,
         # Active < 5000000
         ) %>% 
  
  ggplot(aes(x = continent, y = log(Active), label = Country.Region)) +
  geom_jitter(size = 1.8, width = 0.35, aes(shape = CFR_level, color = CFR_level)) +
  geom_violin(alpha = .5, color = 'grey50', draw_quantiles = c(.25, .5, .75)) +
  labs(title = "Latest Active cases across continents",
       subtitle = "Colored by CFR severity level",
       caption = "created by ViSa (SciArt!!)")

4.4 +plotly tooltip


ggplotly(grouped_cases_df %>% 
  filter(Date == max(Date, na.rm = TRUE)#,
         # Active < 5000000
         ) %>% 
  
  ggplot(aes(x = continent, y = log(Active), label = Country.Region)) +
  geom_jitter(size = 1.8, width = 0.35, aes(shape = CFR_level, color = CFR_level)) +
  geom_violin(alpha = .5, color = 'grey50', draw_quantiles = c(.25, .5, .75)) +
  labs(title = "Latest Active cases across continents",
       subtitle = "Colored by CFR severity level",
       caption = "created by ViSa (SciArt!!)")

  , tooltip = c("log(Active)", "continent", "label"))

4.5 ggforce/geom_sina

grouped_cases_df %>% 
  filter(Date == max(Date, na.rm = TRUE)#,
         # Active < 5000000
         ) %>% 
  
  ggplot(aes(x = continent, y = log(Active), label = Country.Region)) +
  geom_violin(alpha = .5, color = 'grey50', draw_quantiles = c(.25, .5, .75)) +
  ggforce::geom_sina(alpha = .7, size = 1.8, width = 0.35, aes(shape = CFR_level, color = CFR_level)) +
  # geom_jitter() +
  labs(title = "Latest Active cases across continents",
       subtitle = "Colored by CFR severity level",
       caption = "created by ViSa (SciArt!!)")

4.6 +plotly

ggplotly(grouped_cases_df %>% 
  filter(Date == max(Date, na.rm = TRUE)#,
         # Active < 5000000
         ) %>% 
  
  ggplot(aes(x = continent, y = log(Active), label = Country.Region)) +
  geom_violin(alpha = .5, color = 'grey50', draw_quantiles = c(.25, .5, .75)) +
  ggforce::geom_sina(size = 1.8, width = 0.35, aes(shape = CFR_level, color = CFR_level)) +
  # geom_jitter() +
  
  labs(title = "Latest Active cases across continents",
       subtitle = "Colored by CFR severity level",
       caption = "created by ViSa (SciArt!!)")
  
  , tooltip = c("log(Active)", "continent", "label"))
LS0tDQp0aXRsZTogIlRoaXMgaXMgaW4gY29udGludWF0aW9uIG9mIGZpbGU6QWxsX3R5cGVfY2FzZXMuUm1kIg0Kb3V0cHV0Og0KICBodG1sX25vdGVib29rOg0KICAgIGhpZ2hsaWdodDogdGFuZ28NCiAgICBkZl9wcmludDogcGFnZWQNCiAgICB0b2M6IHllcw0KICAgIHRvY19mbG9hdDoNCiAgICAgIGNvbGxhcHNlZDogeWVzDQogICAgICBzbW9vdGhfc2Nyb2xsOiB5ZXMNCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcw0KICAgIHRvY19kZXB0aDogNg0KICBodG1sX2RvY3VtZW50Og0KICAgIHRvYzogeWVzDQogICAgdG9jX2RlcHRoOiAnNicNCiAgICBkZl9wcmludDogcGFnZWQNCi0tLQ0KDQojIG9wdGlvbnMgJiBzZXR0aW5ncw0KDQojIyBjaHVuayBvcHRpb25zDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgcmVzdWx0cz0naGlkZScsIGZpZy5rZWVwPSdhbGwnLCBkcGkgPSAzMDAsIG91dC53aWR0aCA9ICIxMDAlIixhdHRyLm91dHB1dD0nc3R5bGU9Im1heC1oZWlnaHQ6IDMwMHB4OyInKQ0KYGBgDQoNCkNTUyBmb3Igc2Nyb2xsYWJsZSBvdXRwdXQgJiBIZWFkZXIgY29sb3JzDQoNCmBgYHtjc3MsIGVjaG89RkFMU0V9DQouc2Nyb2xsLTEwMCB7DQogIG1heC1oZWlnaHQ6IDEwMHB4Ow0KICBvdmVyZmxvdy15OiBhdXRvOw0KICBiYWNrZ3JvdW5kLWNvbG9yOiBpbmhlcml0Ow0KfQ0KDQp0Ym9keSB0cjpob3ZlciB7DQogIGJhY2tncm91bmQ6ICNkZGRkZGQ7DQp9DQoNCg0KaDEsICNUT0M+dWw+bGkgew0KICBjb2xvcjogI0I2NEQzQTsNCn0NCg0KaDIsICNUT0M+dWw+dWw+bGkgew0KICBjb2xvcjogIzAwMDAwMDsNCn0NCg0KaDMsICNUT0M+dWw+dWw+dWw+bGkgew0KICBjb2xvcjogIzY0M2NiMjsNCn0NCg0KaDQsICNUT0M+dWw+dWw+dWw+dWw+bGkgew0KICBjb2xvcjogI2FlMDA1ODsNCn0NCg0KaDUsICNUT0M+dWw+dWw+dWw+dWw+dWw+bGkgew0KICBjb2xvcjogI2ZmYTQ0NzsNCn0NCg0KaDYsICNUT0M+dWw+dWw+dWw+dWw+dWw+dWw+bGkgew0KICBjb2xvcjogI0RBRTNEOTsNCn0NCg0KDQpgYGANCg0KVHVybmluZyBzY2llbnRpZmljIC8gRXhwb25lbnRpYWwgbnVtYmVycyBvZmYNCg0KYGBge3J9DQpvcHRpb25zKHNjaXBlbiA9IDk5OSkNCmBgYA0KDQpgYGB7ciBlY2hvPUZBTFNFfQ0Kb3B0aW9ucyhyZWFkci5zaG93X3Byb2dyZXNzID0gRkFMU0UpDQpgYGANCg0KIyMgTG9hZGluZyBsaWJzDQoNCmBgYHtyfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGdndGhlbWVzKQ0KYGBgDQoNCmBgYHtyfQ0KbGlicmFyeShsdWJyaWRhdGUpDQpsaWJyYXJ5KGNvdmlkMTkuYW5hbHl0aWNzKQ0KbGlicmFyeShkYXRhLnRhYmxlKQ0KbGlicmFyeShwbG90bHkpDQpsaWJyYXJ5KGdnaGlnaGxpZ2h0KQ0KbGlicmFyeSh6b28pICAgIyB0aGlzIGlzIGZvciBtb3ZpbmcgYXZlcmFnZXMNCiMgbGlicmFyeShnZ1RoZW1lQXNzaXN0KSANCmxpYnJhcnkoZ2x1ZSkNCmxpYnJhcnkoc2NhbGVzKQ0KbGlicmFyeShnZ3RleHQpDQpsaWJyYXJ5KHBhdGNod29yaykNCmxpYnJhcnkoZ2dmb3JjZSkNCmBgYA0KDQojIyBDcmVhdGluZyAmIHNldHRpbmcgY3VzdG9tIHRoZW1lDQoNCmBgYHtyfQ0KDQp0aGVtZV92aW55X2JyaWdodCA8LSBmdW5jdGlvbigpew0KICANCiAgbGlicmFyeShnZ3RoZW1lcykNCiAgDQogIGdndGhlbWVzOjp0aGVtZV9maXZldGhpcnR5ZWlnaHQoKSAlK3JlcGxhY2UlDQogIA0KICB0aGVtZSgNCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KCksDQogICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMyksDQogICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwNCiAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiKSwNCiAgICBwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ3aGl0ZSIpLA0KICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksDQogICAgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9IE5BKSwNCiAgICBsZWdlbmQua2V5ID0gZWxlbWVudF9yZWN0KGZpbGwgPSBOQSksDQogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgc2l6ZSA9IDE0LCBmYWNlID0gInBsYWluIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhbWlseSA9ICJzZXJpZiIpLA0KICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsZmFjZSA9ICJwbGFpbiIsIGZhbWlseSA9ICJzZXJpZiIsIHNpemUgPSA5KSwNCiAgICBwbG90LmNhcHRpb24gPSBlbGVtZW50X3RleHQoaGp1c3QgPSAxLCBjb2xvdXIgPSAibWFyb29uIiwgc2l6ZSA9IDgpDQogICAgICApDQogIH0NCg0KdGhlbWVfc2V0KHRoZW1lX3ZpbnlfYnJpZ2h0KCkpDQpgYGANCg0KIyBEdWFsIGF4aXMgcGxvdA0KDQojIyBMaW5lcGx0OiBEYWlseWNhc2VzIFZzIERhaWx5ZGVhdGhzIHsudGFic2V0IC50YWJzZXQtZmFkZSAudGFic2V0LXBpbGxzfQ0KDQojIyMgRGF0YSBQcmVwLg0KDQpgYGB7cn0NCmdyb3VwZWRfY2FzZXNfZGYgJT4lIGhlYWQoKQ0KYGBgDQoNCmBgYHtyfQ0Kc2NhbGVGYWN0b3IgPSBtYXgoZ3JvdXBlZF9jYXNlc19kZiAlPiUgDQogICAgICAgICAgICAgICAgICAgIGZpbHRlcihDb3VudHJ5LlJlZ2lvbiA9PSAiSW5kaWEiKSAlPiUgDQogICAgICAgICAgICAgICAgICAgIHB1bGwoRGFpbHlfY2FzZXMpKSAvIA0KICAgICAgICAgICAgICBtYXgoZ3JvdXBlZF9jYXNlc19kZiAlPiUgDQogICAgICAgICAgICAgICAgICAgIGZpbHRlcihDb3VudHJ5LlJlZ2lvbiA9PSAiSW5kaWEiKSAlPiUgDQogICAgICAgICAgICAgICAgICAgIHB1bGwoRGFpbHlfZGVhdGhzKSkNCg0Kc2NhbGVGYWN0b3INCmBgYA0KDQojIyMgQmFzaWMgZHVhbCBheGlzIHBsb3QNCg0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IChncm91cGVkX2Nhc2VzX2RmICU+JSBmaWx0ZXIoQ291bnRyeS5SZWdpb24gPT0gIkluZGlhIikpLA0KICAgICAgIGFlcyh4ID0gRGF0ZSkpICsNCiAgZ2VvbV9saW5lKGFlcyh5ID0gRGFpbHlfY2FzZXMpLCBjb2wgPSAiYmx1ZSIpICsNCiAgZ2VvbV9saW5lKGFlcyh5ID0gRGFpbHlfZGVhdGhzICogc2NhbGVGYWN0b3IpLCBjb2wgPSAicmVkIikgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobmFtZSA9ICJEYWlseSBDYXNlcyIsIHNlYy5heGlzID0gc2VjX2F4aXMofi4vc2NhbGVGYWN0b3IsIG5hbWUgPSAiRGFpbHkgRGVhdGhzIikpICsNCiAgDQogIHRoZW1lKA0KICAgIGF4aXMudGl0bGUueS5sZWZ0PWVsZW1lbnRfdGV4dChjb2xvcj0iYmx1ZSIpLA0KICAgIGF4aXMudGV4dC55LmxlZnQ9ZWxlbWVudF90ZXh0KGNvbG9yPSJibHVlIiksDQogICAgYXhpcy50aXRsZS55LnJpZ2h0PWVsZW1lbnRfdGV4dChjb2xvcj0icmVkIiksDQogICAgYXhpcy50ZXh0LnkucmlnaHQ9ZWxlbWVudF90ZXh0KGNvbG9yPSJyZWQiKQ0KICApDQpgYGANCg0KIyMjIEZ1bmN0aW9uMSBkdWFsIGF4aXMgcGxvdA0KDQp0aGlzIGZ1bmN0aW9uIHN1cHBvcnRzIHBhc3Npbmcgb2YgYENvdW50cnkuUmVnaW9uYCBuYW1lcyB3aXRob3V0IHVzaW5nIGBxdW90ZXNgIGJ1dCBpdCBjcmVhdGVzIHByb2JsZW1zIGZvciBjb3VudHJpZXMgdGhhdCBoYXZlIHNwYWNlIGluIG5hbWUuDQoNCmBgYHtyIGZpZy53aWR0aD05LCBmaWcuaGVpZ2h0PTZ9DQpmbl9Db21hcGFyZV9jb25mcm1fdG9fZGVhdGhzIDwtIGZ1bmN0aW9uKENvdW50cnlfc2VsZWN0ZWQgPSBJbmRpYSkgew0KICBDb3VudHJ5X3NlbGVjdGVkX2VucXVvID0gZW5xdW8oQ291bnRyeV9zZWxlY3RlZCkNCiAgDQogIGRhaWx5X2NvbCA9ICIjMzJhNGJhIg0KICBkZWF0aF9jb2wgPSAiI2YwODA4MCINCg0KZ3JvdXBlZF9jYXNlc19kZiAlPiUNCiAgICAgICAgICBmaWx0ZXIoQ291bnRyeS5SZWdpb24gPT0gcXVvX25hbWUoQ291bnRyeV9zZWxlY3RlZF9lbnF1bykpICU+JQ0KDQpnZ3Bsb3QoYWVzKHggPSBEYXRlKSkgKw0KICBnZW9tX2xpbmUoYWVzKHkgPSBEYWlseV9jYXNlcyksIGNvbCA9IGRhaWx5X2NvbCwgc2l6ZSA9IDAuOCkgKw0KICBnZW9tX2xpbmUoYWVzKHkgPSBEYWlseV9kZWF0aHMgKiBzY2FsZUZhY3RvciksIGNvbCA9IGRlYXRoX2NvbCwgc2l6ZSA9IDAuOCwgDQogICAgICAgICAgICBzaXplID0gMC44LCBhbHBoYSA9IDAuOCkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobmFtZSA9ICJEYWlseSBDYXNlcyIsIHNlYy5heGlzID0gc2VjX2F4aXMofi4vc2NhbGVGYWN0b3IsIG5hbWUgPSAiRGFpbHkgRGVhdGhzIiksDQogICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBzY2FsZXM6OmNvbW1hX2Zvcm1hdCgpKSArDQogIHNjYWxlX3hfZGF0ZShkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwgZGF0ZV9sYWJlbHMgPSAiJWIiKSArDQogIA0KICB0aGVtZV9leGNlbF9uZXcoKSArDQoNCiAgdGhlbWUoDQogICAgYXhpcy50aXRsZS55LmxlZnQ9ZWxlbWVudF90ZXh0KGNvbG9yPWRhaWx5X2NvbCksDQogICAgYXhpcy50ZXh0LnkubGVmdD1lbGVtZW50X3RleHQoY29sb3I9ZGFpbHlfY29sKSwNCiAgICBheGlzLnRpdGxlLnkucmlnaHQ9ZWxlbWVudF90ZXh0KGNvbG9yPWRlYXRoX2NvbCksDQogICAgYXhpcy50ZXh0LnkucmlnaHQ9ZWxlbWVudF90ZXh0KGNvbG9yPWRlYXRoX2NvbCksDQogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gInBsYWluIiwgZmFtaWx5ID0gInNlcmlmIiwgc2l6ZSA9IDE0KQ0KICApICsgDQogIA0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF9tYXJrZG93bigpICkgKw0KICANCiAgbGFicyh0aXRsZSA9IGdsdWUoIjxpPntxdW9fbmFtZShlbnF1byhDb3VudHJ5X3NlbGVjdGVkKSl9PC9pPjogRGFpbHkgY29uZmlybWVkICYgZGVhdGggY2FzZXMiKSwNCiAgICAgICBjYXB0aW9uID0gImNyZWF0ZWQgYnkgVmlTYSAoU2NpQXJ0ISEpIikgKw0KICBjb29yZF9maXhlZChyYXRpbyA9IC4wMDI4KQ0KfQ0KDQpmbl9Db21hcGFyZV9jb25mcm1fdG9fZGVhdGhzKEdlcm1hbnkpDQpgYGANCg0KIyMjIEZ1bmN0aW9uMiBkdWFsIGF4aXMgcGxvdA0KDQp0aGlzIGZ1bmN0aW9uIHJlcXVpcmVzIHBhc3Npbmcgb2YgYENvdW50cnkuUmVnaW9uYCBuYW1lcyB3aXRoaW4gYHF1b3Rlc2Agb25seSBzdXBwb3J0IGNvdW50cnkgbmFtZXMgdGhhdCBoYXZlIHNwYWNlIGluIGl0Lg0KDQpgYGB7ciBmaWcud2lkdGg9OSwgZmlnLmhlaWdodD02fQ0KZm5fQ29tYXBhcmVfY29uZnJtX3RvX2RlYXRocyA8LSBmdW5jdGlvbihDb3VudHJ5X3NlbGVjdGVkID0gIkluZGlhIikgew0KICAjIENvdW50cnlfc2VsZWN0ZWRfZW5xdW8gPSBlbnF1byhDb3VudHJ5X3NlbGVjdGVkKQ0KICANCiAgZGFpbHlfY29sID0gIiMzMmE0YmEiDQogIGRlYXRoX2NvbCA9ICIjZjA4MDgwIg0KDQpncm91cGVkX2Nhc2VzX2RmICU+JQ0KICAgICAgICAgIGZpbHRlcihDb3VudHJ5LlJlZ2lvbiA9PSBDb3VudHJ5X3NlbGVjdGVkKSAlPiUNCg0KZ2dwbG90KGFlcyh4ID0gRGF0ZSkpICsNCiAgZ2VvbV9saW5lKGFlcyh5ID0gRGFpbHlfY2FzZXMpLCBjb2wgPSBkYWlseV9jb2wsIHNpemUgPSAwLjgpICsNCiAgZ2VvbV9saW5lKGFlcyh5ID0gRGFpbHlfZGVhdGhzICogc2NhbGVGYWN0b3IpLCBjb2wgPSBkZWF0aF9jb2wsIA0KICAgICAgICAgICAgc2l6ZSA9IDAuOCwgYWxwaGEgPSAwLjgpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKG5hbWUgPSAiRGFpbHkgQ2FzZXMiLCBzZWMuYXhpcyA9IHNlY19heGlzKH4uL3NjYWxlRmFjdG9yLCBuYW1lID0gIkRhaWx5IERlYXRocyIpLA0KICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gc2NhbGVzOjpjb21tYV9mb3JtYXQoKSkgKw0KICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAiMSBtb250aCIsIGRhdGVfbGFiZWxzID0gIiViIikgKw0KICANCiAgdGhlbWVfZXhjZWxfbmV3KCkgKw0KICB0aGVtZSgNCiAgICBheGlzLnRpdGxlLnkubGVmdD1lbGVtZW50X3RleHQoY29sb3I9ZGFpbHlfY29sKSwNCiAgICBheGlzLnRleHQueS5sZWZ0PWVsZW1lbnRfdGV4dChjb2xvcj1kYWlseV9jb2wpLA0KICAgIGF4aXMudGl0bGUueS5yaWdodD1lbGVtZW50X3RleHQoY29sb3I9ZGVhdGhfY29sKSwNCiAgICBheGlzLnRleHQueS5yaWdodD1lbGVtZW50X3RleHQoY29sb3I9ZGVhdGhfY29sKSwNCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAicGxhaW4iLCBmYW1pbHkgPSAic2VyaWYiLCBzaXplID0gMTQpDQogICkgKyANCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfbWFya2Rvd24oKSkgKw0KICBsYWJzKHRpdGxlID0gZ2x1ZSgiPGk+e0NvdW50cnlfc2VsZWN0ZWR9PC9pPjogRGFpbHkgY29uZmlybWVkICYgZGVhdGggY2FzZXMiKSwNCiAgICAgICBjYXB0aW9uID0gImNyZWF0ZWQgYnkgVmlTYSAoU2NpQXJ0ISEpIikgKw0KICAgIA0KICBjb29yZF9maXhlZChyYXRpbyA9IC4wMDI4KQ0KICAjIGNvb3JkX2ZpeGVkKHJhdGlvID0gLjAwOCkgDQp9DQoNCnBsdDEgPC0gZm5fQ29tYXBhcmVfY29uZnJtX3RvX2RlYXRocygiVW5pdGVkIEtpbmdkb20iKQ0KcGx0MQ0KYGBgDQoNCiMjIyBwbG90bHkNCg0KYGBge3J9DQpnZ3Bsb3RseShmbl9Db21hcGFyZV9jb25mcm1fdG9fZGVhdGhzKCJVbml0ZWQgS2luZ2RvbSIpKQ0KYGBgDQoNCiMjIyBDRlIgbGV2ZWwgcGx0DQoNCmBgYHtyIGZpZy53aWR0aD05fQ0KDQpmbl9DRlIgPC0gZnVuY3Rpb24oQ291bnRyeV9zZWxlY3RlZCA9ICJJbmRpYSIpIHsNCiAgZ3JvdXBlZF9jYXNlc19kZiAlPiUgDQogICAgZmlsdGVyKENvdW50cnkuUmVnaW9uID09IENvdW50cnlfc2VsZWN0ZWQpICU+JSANCiAgICANCiAgICBnZ3Bsb3QoYWVzKHggPSBEYXRlLCB5ID0gQ2FzZV9GYXRhbGl0eV9SYXRpbywgY29sID0gQ0ZSX2xldmVsLCBncm91cCA9IDEpKSArDQogICAgZ2VvbV9saW5lKHNpemUgPSAwLjgpICsNCiAgICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gbGFiZWxfZG9sbGFyKHByZWZpeCA9ICIiLCBzdWZmaXggPSAiJSIpKSArDQogICAgc2NhbGVfeF9kYXRlKGRhdGVfYnJlYWtzID0gIjEgbW9udGgiLCBkYXRlX2xhYmVscyA9ICIlYiIpICsNCiAgICB0aGVtZV9leGNlbF9uZXcoKSArDQogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsDQogICAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gInBsYWluIiwgZmFtaWx5ID0gInNlcmlmIiwgc2l6ZSA9IDE0KSkgKw0KICAgIA0KICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X21hcmtkb3duKCkpICsNCiAgICBsYWJzKHRpdGxlID0gZ2x1ZSgiPGk+e0NvdW50cnlfc2VsZWN0ZWR9PC9pPjogQ2FzZSBGYXRhbGl0eSBSYXRpbyglKSAmIGxldmVsIiksDQogICAgICAgICB5ID0gIkNGUiglKSIsDQogICAgICAgICBjYXB0aW9uID0gImNyZWF0ZWQgYnkgVmlTYSAoU2NpQXJ0ISEpIikgKw0KICAgICMgeWxhYihsYWJlbCA9ICJDRlIgKCUpIikNCiAgICAgIA0KICAgIGNvb3JkX2ZpeGVkKHJhdGlvID0gNCkgDQp9DQogIA0KcGx0MiA8LSBmbl9DRlIoIlVuaXRlZCBLaW5nZG9tIikNCnBsdDINCmBgYA0KDQojIyMgUGF0Y2hlZCBQbG90cw0KDQpgYGB7ciBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aCA9IDl9DQoNCnBsdDEgLyBwbHQyDQpgYGANCg0KYGBge3J9DQpnZ3NhdmUoZmlsZW5hbWUgPSAiVUtfRGFpbHljYXNlcy5wbmciLCBkcGkgPSAzMDApDQpgYGANCg0KIyMgQ29scGx0OiBEYWlseWNhc2VzIFZzIERhaWx5ZGVhdGhzIHsudGFic2V0IC50YWJzZXQtZmFkZSAudGFic2V0LXBpbGxzfQ0KDQojIyMgQmFzaWMgZHVhbCBheGlzIHBsb3QNCg0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IChncm91cGVkX2Nhc2VzX2RmICU+JSBmaWx0ZXIoQ291bnRyeS5SZWdpb24gPT0gIkluZGlhIikpLA0KICAgICAgIGFlcyh4ID0gRGF0ZSkpICsNCiAgZ2VvbV9jb2woYWVzKHkgPSBEYWlseV9jYXNlcyksIGNvbCA9ICJibHVlIikgKw0KICBnZW9tX2xpbmUoYWVzKHkgPSBEYWlseV9kZWF0aHMgKiBzY2FsZUZhY3RvciksIGNvbCA9ICJyZWQiKSArDQogIHNjYWxlX3lfY29udGludW91cyhuYW1lID0gIkRhaWx5IENhc2VzIiwgc2VjLmF4aXMgPSBzZWNfYXhpcyh+Li9zY2FsZUZhY3RvciwgbmFtZSA9ICJEYWlseSBEZWF0aHMiKSkgKw0KICANCiAgdGhlbWUoDQogICAgYXhpcy50aXRsZS55LmxlZnQ9ZWxlbWVudF90ZXh0KGNvbG9yPSJibHVlIiksDQogICAgYXhpcy50ZXh0LnkubGVmdD1lbGVtZW50X3RleHQoY29sb3I9ImJsdWUiKSwNCiAgICBheGlzLnRpdGxlLnkucmlnaHQ9ZWxlbWVudF90ZXh0KGNvbG9yPSJyZWQiKSwNCiAgICBheGlzLnRleHQueS5yaWdodD1lbGVtZW50X3RleHQoY29sb3I9InJlZCIpDQogICkNCmBgYA0KDQojIyMgRnVuY3Rpb24xIGR1YWwgYXhpcyBwbG90DQoNCnRoaXMgZnVuY3Rpb24gc3VwcG9ydHMgcGFzc2luZyBvZiBgQ291bnRyeS5SZWdpb25gIG5hbWVzIHdpdGhvdXQgdXNpbmcgYHF1b3Rlc2AgYnV0IGl0IGNyZWF0ZXMgcHJvYmxlbXMgZm9yIGNvdW50cmllcyB0aGF0IGhhdmUgc3BhY2UgaW4gbmFtZS4NCg0KYGBge3IgZmlnLndpZHRoPTksIGZpZy5oZWlnaHQ9Nn0NCmZuX0NvbWFwYXJlX2NvbmZybV90b19kZWF0aHMgPC0gZnVuY3Rpb24oQ291bnRyeV9zZWxlY3RlZCA9IEluZGlhKSB7DQogIENvdW50cnlfc2VsZWN0ZWRfZW5xdW8gPSBlbnF1byhDb3VudHJ5X3NlbGVjdGVkKQ0KICANCiAgZGFpbHlfY29sID0gIiMzMmE0YmEiDQogIGRlYXRoX2NvbCA9ICIjZjA4MDgwIg0KDQpncm91cGVkX2Nhc2VzX2RmICU+JQ0KICAgICAgICAgIGZpbHRlcihDb3VudHJ5LlJlZ2lvbiA9PSBxdW9fbmFtZShDb3VudHJ5X3NlbGVjdGVkX2VucXVvKSkgJT4lDQoNCmdncGxvdChhZXMoeCA9IERhdGUpKSArDQogIGdlb21fY29sKGFlcyh5ID0gRGFpbHlfY2FzZXMpLCBmaWxsID0gZGFpbHlfY29sLCBzaXplID0gMC44KSArDQogIGdlb21fbGluZShhZXMoeSA9IERhaWx5X2RlYXRocyAqIHNjYWxlRmFjdG9yKSwgY29sID0gZGVhdGhfY29sLCBzaXplID0gMC44LCANCiAgICAgICAgICAgIHNpemUgPSAwLjgsIGFscGhhID0gMC44KSArDQogIHNjYWxlX3lfY29udGludW91cyhuYW1lID0gIkRhaWx5IENhc2VzIiwgc2VjLmF4aXMgPSBzZWNfYXhpcyh+Li9zY2FsZUZhY3RvciwgbmFtZSA9ICJEYWlseSBEZWF0aHMiKSwNCiAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IHNjYWxlczo6Y29tbWFfZm9ybWF0KCkpICsNCiAgc2NhbGVfeF9kYXRlKGRhdGVfYnJlYWtzID0gIjEgbW9udGgiLCBkYXRlX2xhYmVscyA9ICIlYiIpICsNCiAgDQogIHRoZW1lX2V4Y2VsX25ldygpICsNCg0KICB0aGVtZSgNCiAgICBheGlzLnRpdGxlLnkubGVmdD1lbGVtZW50X3RleHQoY29sb3I9ZGFpbHlfY29sKSwNCiAgICBheGlzLnRleHQueS5sZWZ0PWVsZW1lbnRfdGV4dChjb2xvcj1kYWlseV9jb2wpLA0KICAgIGF4aXMudGl0bGUueS5yaWdodD1lbGVtZW50X3RleHQoY29sb3I9ZGVhdGhfY29sKSwNCiAgICBheGlzLnRleHQueS5yaWdodD1lbGVtZW50X3RleHQoY29sb3I9ZGVhdGhfY29sKSwNCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAicGxhaW4iLCBmYW1pbHkgPSAic2VyaWYiLCBzaXplID0gMTQpDQogICkgKyANCiAgDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X21hcmtkb3duKCkgKSArDQogIA0KICBsYWJzKHRpdGxlID0gZ2x1ZSgiPGk+e3F1b19uYW1lKGVucXVvKENvdW50cnlfc2VsZWN0ZWQpKX08L2k+OiBEYWlseSBjb25maXJtZWQgJiBkZWF0aCBjYXNlcyIpLA0KICAgICAgIGNhcHRpb24gPSAiY3JlYXRlZCBieSBWaVNhIChTY2lBcnQhISkiKSArDQogIGNvb3JkX2ZpeGVkKHJhdGlvID0gLjAwMjgpDQp9DQoNCmZuX0NvbWFwYXJlX2NvbmZybV90b19kZWF0aHMoR2VybWFueSkNCmBgYA0KDQojIyMgRnVuY3Rpb24yIGR1YWwgYXhpcyBwbG90DQoNCnRoaXMgZnVuY3Rpb24gcmVxdWlyZXMgcGFzc2luZyBvZiBgQ291bnRyeS5SZWdpb25gIG5hbWVzIHdpdGhpbiBgcXVvdGVzYCBvbmx5IHN1cHBvcnQgY291bnRyeSBuYW1lcyB0aGF0IGhhdmUgc3BhY2UgaW4gaXQuDQoNCmBgYHtyIGZpZy53aWR0aD05LCBmaWcuaGVpZ2h0PTZ9DQpmbl9Db21hcGFyZV9jb25mcm1fdG9fZGVhdGhzIDwtIGZ1bmN0aW9uKENvdW50cnlfc2VsZWN0ZWQgPSAiSW5kaWEiKSB7DQogICMgQ291bnRyeV9zZWxlY3RlZF9lbnF1byA9IGVucXVvKENvdW50cnlfc2VsZWN0ZWQpDQogIA0KICBkYWlseV9jb2wgPSAiIzMyYTRiYSINCiAgZGVhdGhfY29sID0gIiNmMDgwODAiDQoNCmdyb3VwZWRfY2FzZXNfZGYgJT4lDQogICAgICAgICAgZmlsdGVyKENvdW50cnkuUmVnaW9uID09IENvdW50cnlfc2VsZWN0ZWQpICU+JQ0KDQpnZ3Bsb3QoYWVzKHggPSBEYXRlKSkgKw0KICBnZW9tX2NvbChhZXMoeSA9IERhaWx5X2Nhc2VzKSwgZmlsbCA9IGRhaWx5X2NvbCwgc2l6ZSA9IDAuOCkgKw0KICBnZW9tX2xpbmUoYWVzKHkgPSBEYWlseV9kZWF0aHMgKiBzY2FsZUZhY3RvciksIGNvbCA9IGRlYXRoX2NvbCwgDQogICAgICAgICAgICBzaXplID0gMC44LCBhbHBoYSA9IDAuOCkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobmFtZSA9ICJEYWlseSBDYXNlcyIsIHNlYy5heGlzID0gc2VjX2F4aXMofi4vc2NhbGVGYWN0b3IsIG5hbWUgPSAiRGFpbHkgRGVhdGhzIiksDQogICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBzY2FsZXM6OmNvbW1hX2Zvcm1hdCgpKSArDQogIHNjYWxlX3hfZGF0ZShkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwgZGF0ZV9sYWJlbHMgPSAiJWIiKSArDQogIA0KICB0aGVtZV9leGNlbF9uZXcoKSArDQogIHRoZW1lKA0KICAgIGF4aXMudGl0bGUueS5sZWZ0PWVsZW1lbnRfdGV4dChjb2xvcj1kYWlseV9jb2wpLA0KICAgIGF4aXMudGV4dC55LmxlZnQ9ZWxlbWVudF90ZXh0KGNvbG9yPWRhaWx5X2NvbCksDQogICAgYXhpcy50aXRsZS55LnJpZ2h0PWVsZW1lbnRfdGV4dChjb2xvcj1kZWF0aF9jb2wpLA0KICAgIGF4aXMudGV4dC55LnJpZ2h0PWVsZW1lbnRfdGV4dChjb2xvcj1kZWF0aF9jb2wpLA0KICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJwbGFpbiIsIGZhbWlseSA9ICJzZXJpZiIsIHNpemUgPSAxNCkNCiAgKSArIA0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF9tYXJrZG93bigpKSArDQogIGxhYnModGl0bGUgPSBnbHVlKCI8aT57Q291bnRyeV9zZWxlY3RlZH08L2k+OiBEYWlseSBjb25maXJtZWQgJiBkZWF0aCBjYXNlcyIpLA0KICAgICAgIGNhcHRpb24gPSAiY3JlYXRlZCBieSBWaVNhIChTY2lBcnQhISkiKSArDQogICAgDQogIGNvb3JkX2ZpeGVkKHJhdGlvID0gLjAwMjgpIA0KfQ0KDQpwbHQxIDwtIGZuX0NvbWFwYXJlX2NvbmZybV90b19kZWF0aHMoIlVuaXRlZCBLaW5nZG9tIikNCnBsdDENCmBgYA0KDQojIyMgcGxvdGx5DQoNCmBgYHtyfQ0KZ2dwbG90bHkoZm5fQ29tYXBhcmVfY29uZnJtX3RvX2RlYXRocygiVW5pdGVkIEtpbmdkb20iKSkNCmBgYA0KDQojIyMgQ0ZSIGxldmVsIHBsdA0KDQpgYGB7ciBmaWcud2lkdGg9OX0NCg0KZm5fQ0ZSIDwtIGZ1bmN0aW9uKENvdW50cnlfc2VsZWN0ZWQgPSAiSW5kaWEiKSB7DQogIGdyb3VwZWRfY2FzZXNfZGYgJT4lIA0KICAgIGZpbHRlcihDb3VudHJ5LlJlZ2lvbiA9PSBDb3VudHJ5X3NlbGVjdGVkKSAlPiUgDQogICAgDQogICAgZ2dwbG90KGFlcyh4ID0gRGF0ZSwgeSA9IENhc2VfRmF0YWxpdHlfUmF0aW8sIGNvbCA9IENGUl9sZXZlbCwgZ3JvdXAgPSAxKSkgKw0KICAgIGdlb21fbGluZShzaXplID0gMC44KSArDQogICAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IGxhYmVsX2RvbGxhcihwcmVmaXggPSAiIiwgc3VmZml4ID0gIiUiKSkgKw0KICAgIHNjYWxlX3hfZGF0ZShkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwgZGF0ZV9sYWJlbHMgPSAiJWIiKSArDQogICAgdGhlbWVfZXhjZWxfbmV3KCkgKw0KICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLA0KICAgICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJwbGFpbiIsIGZhbWlseSA9ICJzZXJpZiIsIHNpemUgPSAxNCkpICsNCiAgICANCiAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF9tYXJrZG93bigpKSArDQogICAgbGFicyh0aXRsZSA9IGdsdWUoIjxpPntDb3VudHJ5X3NlbGVjdGVkfTwvaT46IENhc2UgRmF0YWxpdHkgUmF0aW8oJSkgJiBsZXZlbCIpLA0KICAgICAgICAgeSA9ICJDRlIoJSkiLA0KICAgICAgICAgY2FwdGlvbiA9ICJjcmVhdGVkIGJ5IFZpU2EgKFNjaUFydCEhKSIpICsNCiAgICAjIHlsYWIobGFiZWwgPSAiQ0ZSICglKSIpDQogICAgICANCiAgICBjb29yZF9maXhlZChyYXRpbyA9IDQpIA0KfQ0KICANCnBsdDIgPC0gZm5fQ0ZSKCJVbml0ZWQgS2luZ2RvbSIpDQpwbHQyDQpgYGANCg0KIyMjIFBhdGNoZWQgUGxvdHMNCg0KYGBge3IgZmlnLmhlaWdodD04LCBmaWcud2lkdGggPSA5fQ0KDQpwbHQxIC8gcGx0Mg0KYGBgDQoNCiMgTGF0ZXN0IFdlZWsgcGxvdHMNCg0KIyMgVG9wIDEwIGluIDcgZGF5cyB7LnRhYnNldCAudGFic2V0LWZhZGUgLnRhYnNldC1waWxsc30NCg0KIyMjIGZhY2V0IGJ5IERhdGUNCg0KYGBge3IgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9MTB9DQoNCmRmX3N0YWNrICU+JSANCiAgZmlsdGVyKHN0cl9zdGFydHMoZGZfc3RhY2skQ2FzZXNfdHlwZSwgcGF0dGVybiA9ICJEYWlseV8iKSwNCiAgICAgICAgICAgICAgICAgICAgRGF0ZSA+IChtYXgoRGF0ZSwgbmEucm0gPSBUUlVFKSAtIDgpICYgRGF0ZSA8IG1heChEYXRlLCBuYS5ybSA9IFRSVUUpKSAlPiUgDQogIGdyb3VwX2J5KENvdW50cnkuUmVnaW9uLCBEYXRlLCBDYXNlc190eXBlKSAlPiUgDQogIHN1bW1hcmlzZShDYXNlc19jb3VudCA9IHN1bShDYXNlc19jb3VudCkpICU+JQ0KICBncm91cF9ieShEYXRlLCBDYXNlc190eXBlKSAlPiUgDQogIHNsaWNlX21heChvcmRlcl9ieSA9IENhc2VzX2NvdW50LCBuID0gNSkgJT4lIA0KICBtdXRhdGUoQ2FzZXNfc2l6ZSA9IENhc2VzX2NvdW50IC8gc3VtKENhc2VzX2NvdW50KSkgJT4lIA0KICB1bmdyb3VwKCkgJT4lIA0KICANCiAgZ2dwbG90KGFlcyh4ID0gQ2FzZXNfdHlwZSwgeSA9IENvdW50cnkuUmVnaW9uKSkgKw0KICBnZW9tX3BvaW50KHNoYXBlID0gMjEsIGFlcyhzaXplID0gQ2FzZXNfc2l6ZSwgY29sb3IgPSBDYXNlc190eXBlKSwgZmlsbD0iI2Y4ZjJlNCIsIHN0cm9rZT0zKSArDQogICMgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWVfd3NqKCkgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSwNCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSwNCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLA0KICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsIGZhbWlseSA9ICJzZXJpZiIsIHNpemUgPSAyMCksDQogICAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJwbGFpbiIsIGZhbWlseSA9ICJzZXJpZiIsIHNpemUgPSAxMiksDQogICAgICAgIHBsb3QuY2FwdGlvbiA9IGVsZW1lbnRfdGV4dChmYWNlID0gInBsYWluIiwgZmFtaWx5ID0gInNlcmlmIiwgc2l6ZSA9IDkpKSArDQogIHNjYWxlX2NvbG9yX3RhYmxlYXUocGFsZXR0ZSA9ICJUYWJsZWF1IDEwIikgKw0KICAjIHNjYWxlX2NvbG9yX3dzaihwYWxldHRlID0gImNvbG9yczYiKSArDQogIA0KICBmYWNldF93cmFwKH5EYXRlKSArDQogIGxhYnModGl0bGUgPSAiVG9wIDUgQ291bnRyaWVzIGZvciBhbGwgdHlwZSBvZiBEYWlseSBjYXNlcyIsDQogICAgICAgc3VidGl0bGUgPSAiRm9yIExhdGVzdCA3IGRheXMgKFNpemUgYmFzZWQgb24gZWFjaCBjYXRlZ29yeSBjb3VudCBmb3Igc2FtZSBkYXRlKSIsDQogICAgICAgY2FwdGlvbiA9ICJjcmVhdGVkIGJ5IFZpU2EgKFNjaUFydCEhKSIpICsNCiAgY29vcmRfY2FydGVzaWFuKGNsaXAgPSAib2ZmIikNCmBgYA0KDQojIyMgK2dndGV4dCBjb2xyIGF4aXMNCg0KcmVmOiA8aHR0cHM6Ly93aWxrZWxhYi5vcmcvZ2d0ZXh0Lz4NCg0Kc29sdXRpb24gZnJvbTogPGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzY1NjUyNjAwL2hvdy10by11c2UtZ2d0ZXh0LXRvLWNvbG9yLWF4aXMtZGF0YS1sYWJlbHMtaW4tci82NTY1MjgwMSM2NTY1MjgwMT4NCg0KYGBge3IgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9MTB9DQoNCmNvbG9yID0gYyhEYWlseV9jYXNlcyA9ICIjMjU5NmJlIiwgRGFpbHlfZGVhdGhzID0gIiNmMjhlMmIiLCBEYWlseV9yZWNvdmVyZWQgPSAiI2UxNTc1OSIpDQoNCmRmX3N0YWNrICU+JSANCiAgZmlsdGVyKHN0cl9zdGFydHMoZGZfc3RhY2skQ2FzZXNfdHlwZSwgcGF0dGVybiA9ICJEYWlseV8iKSwNCiAgICAgICAgICAgICAgICAgICAgRGF0ZSA+IChtYXgoRGF0ZSwgbmEucm0gPSBUUlVFKSAtIDgpICYgRGF0ZSA8IG1heChEYXRlLCBuYS5ybSA9IFRSVUUpKSAlPiUgDQogIGdyb3VwX2J5KENvdW50cnkuUmVnaW9uLCBEYXRlLCBDYXNlc190eXBlKSAlPiUgDQogIHN1bW1hcmlzZShDYXNlc19jb3VudCA9IHN1bShDYXNlc19jb3VudCkpICU+JQ0KICBncm91cF9ieShEYXRlLCBDYXNlc190eXBlKSAlPiUgDQogIHNsaWNlX21heChvcmRlcl9ieSA9IENhc2VzX2NvdW50LCBuID0gNSkgJT4lIA0KICBtdXRhdGUoQ2FzZXNfc2l6ZSA9IENhc2VzX2NvdW50IC8gc3VtKENhc2VzX2NvdW50KSkgJT4lIA0KICB1bmdyb3VwKCkgJT4lIA0KICAjIG11dGF0ZShDYXNlc190eXBlID0gZ2x1ZSgiPGkgc3R5bGU9J2NvbG9yOntjb2xvcn0nPntDYXNlc190eXBlfTwvaT4iKSkgJT4lIA0KICBtdXRhdGUoQ2FzZXNfdHlwZSA9IGdsdWUoIjxpIHN0eWxlPSdjb2xvcjoge2NvbG9yW0Nhc2VzX3R5cGVdfSc+e0Nhc2VzX3R5cGV9PC9pPiIpKSAlPiUgDQoNCiAgZ2dwbG90KGFlcyh4ID0gQ2FzZXNfdHlwZSwgeSA9IENvdW50cnkuUmVnaW9uKSkgKw0KICBnZW9tX3BvaW50KHNoYXBlID0gMjEsIGFlcyhzaXplID0gQ2FzZXNfc2l6ZSwgY29sb3IgPSBDYXNlc190eXBlKSwgZmlsbD0iI2Y4ZjJlNCIsIHN0cm9rZT0zKSArDQogICN0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZV93c2ooKSArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApLA0KICAgICAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpLA0KICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsDQogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgZmFtaWx5ID0gInNlcmlmIiwgc2l6ZSA9IDIwKSwNCiAgICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gInBsYWluIiwgZmFtaWx5ID0gInNlcmlmIiwgc2l6ZSA9IDEyKSwNCiAgICAgICAgcGxvdC5jYXB0aW9uID0gZWxlbWVudF90ZXh0KGZhY2UgPSAicGxhaW4iLCBmYW1pbHkgPSAic2VyaWYiLCBzaXplID0gOSkpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X21hcmtkb3duKCkpICsNCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIiMyNTk2YmUiLCAiI2UxNTc1OSIsICIjZjI4ZTJiIikpICsNCiAgIyBzY2FsZV9jb2xvcl90YWJsZWF1KHBhbGV0dGUgPSAiVGFibGVhdSAxMCIpICsNCiAgIyBzY2FsZV9jb2xvcl93c2oocGFsZXR0ZSA9ICJjb2xvcnM2IikgKw0KICBmYWNldF93cmFwKH5EYXRlKSArDQogIGxhYnModGl0bGUgPSAiVG9wIDUgQ291bnRyaWVzIGZvciBhbGwgdHlwZSBvZiBEYWlseSBjYXNlcyIsDQogICAgICAgc3VidGl0bGUgPSAiRm9yIExhdGVzdCA3IGRheXMgc2VwYXJhdGVkIGJ5IGVhY2ggZGF0ZSIsDQogICAgICAgY2FwdGlvbiA9ICJjcmVhdGVkIGJ5IFZpU2EgKFNjaUFydCEhKSIpICsNCiAgY29vcmRfY2FydGVzaWFuKGNsaXAgPSAib2ZmIikNCmBgYA0KDQojIyMgd29ya2luZyBzb2x1dGlvbg0KDQpgYGB7ciBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD0xMH0NCg0KY29sb3IgPSBjKERhaWx5X2Nhc2VzID0gIiMyNTk2YmUiLCBEYWlseV9kZWF0aHMgPSAiI2UxNTc1OSIsIERhaWx5X3JlY292ZXJlZCA9ICIjZjI4ZTJiIikNCg0KcmVhZC5jc3YoImh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9qb2huc25vdzA5L2NvdmlkMTktZGZfc3RhY2stY29kZS9tYWluL2RmX3N0YWNrX2xpbWl0ZWQuY3N2IikgJT4lDQogIG11dGF0ZShDYXNlc190eXBlID0gZ2x1ZSgiPGkgc3R5bGU9J2NvbG9yOiB7Y29sb3JbQ2FzZXNfdHlwZV19Jz57Q2FzZXNfdHlwZX08L2k+IikpICU+JSANCg0KICBnZ3Bsb3QoYWVzKHggPSBDYXNlc190eXBlLCB5ID0gQ291bnRyeS5SZWdpb24pKSArDQogIGdlb21fcG9pbnQoc2hhcGUgPSAyMSwgYWVzKHNpemUgPSBDYXNlc19zaXplLCBjb2xvciA9IENhc2VzX3R5cGUpLCBmaWxsPSIjZjhmMmU0Iiwgc3Ryb2tlPTMpICsNCiAgI3RoZW1lX21pbmltYWwoKSArDQogIHRoZW1lX3dzaigpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCksDQogICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCksDQogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwNCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiLCBmYW1pbHkgPSAic2VyaWYiLCBzaXplID0gMjApLA0KICAgICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAicGxhaW4iLCBmYW1pbHkgPSAic2VyaWYiLCBzaXplID0gMTIpLA0KICAgICAgICBwbG90LmNhcHRpb24gPSBlbGVtZW50X3RleHQoZmFjZSA9ICJwbGFpbiIsIGZhbWlseSA9ICJzZXJpZiIsIHNpemUgPSA5KSkgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfbWFya2Rvd24oKSkgKw0KICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiIzI1OTZiZSIsICIjZTE1NzU5IiwgIiNmMjhlMmIiKSkgKw0KICAjIHNjYWxlX2NvbG9yX3RhYmxlYXUocGFsZXR0ZSA9ICJUYWJsZWF1IDEwIikgKw0KICAjIHNjYWxlX2NvbG9yX3dzaihwYWxldHRlID0gImNvbG9yczYiKSArDQogIGZhY2V0X3dyYXAofkRhdGUpICsNCiAgbGFicyh0aXRsZSA9ICJUb3AgNSBDb3VudHJpZXMgZm9yIGFsbCB0eXBlIG9mIERhaWx5IGNhc2VzIiwNCiAgICAgICBzdWJ0aXRsZSA9ICJGb3IgTGF0ZXN0IDcgZGF5cyAoU2l6ZSBiYXNlZCBvbiBlYWNoIGNhdGVnb3J5IGNvdW50IGZvciBzYW1lIGRhdGUpIiwNCiAgICAgICBjYXB0aW9uID0gImNyZWF0ZWQgYnkgVmlTYSAoU2NpQXJ0ISEpIikgKw0KICBjb29yZF9jYXJ0ZXNpYW4oY2xpcCA9ICJvZmYiKQ0KYGBgDQoNCiMjIyBmYWNldCBieSBDYXNlc190eXBlDQoNCmBgYHtyIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTZ9DQoNCmRmX3N0YWNrICU+JSANCiAgZmlsdGVyKHN0cl9zdGFydHMoZGZfc3RhY2skQ2FzZXNfdHlwZSwgcGF0dGVybiA9ICJEYWlseV8iKSwNCiAgICAgICAgIERhdGUgPiAobWF4KERhdGUsIG5hLnJtID0gVFJVRSkgLSA4KSAmIERhdGUgPCBtYXgoRGF0ZSwgbmEucm0gPSBUUlVFKSkgJT4lIA0KICBncm91cF9ieShDb3VudHJ5LlJlZ2lvbiwgRGF0ZSwgQ2FzZXNfdHlwZSkgJT4lIA0KICBzdW1tYXJpc2UoQ2FzZXNfY291bnQgPSBzdW0oQ2FzZXNfY291bnQpKSAlPiUNCiAgZ3JvdXBfYnkoRGF0ZSwgQ2FzZXNfdHlwZSkgJT4lIA0KICBzbGljZV9tYXgob3JkZXJfYnkgPSBDYXNlc19jb3VudCwgbiA9IDUpICU+JSANCiAgbXV0YXRlKENhc2VzX3NpemUgPSBDYXNlc19jb3VudCAvIHN1bShDYXNlc19jb3VudCkpICU+JSANCiAgdW5ncm91cCgpICU+JSANCiAgDQogIGdncGxvdChhZXMoeCA9IERhdGUsIHkgPSBDb3VudHJ5LlJlZ2lvbikpICsNCiAgZ2VvbV9wb2ludChzaGFwZSA9IDIxLCBhZXMoc2l6ZSA9IENhc2VzX3NpemUsIGNvbG9yID0gRGF0ZSksIGZpbGw9IiNmOGYyZTQiLCBzdHJva2U9MykgKw0KICAjIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lX3dzaigpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCksDQogICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCksDQogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwNCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiLCBmYW1pbHkgPSAic2VyaWYiLCBzaXplID0gMjApLA0KICAgICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAicGxhaW4iLCBmYW1pbHkgPSAic2VyaWYiLCBzaXplID0gMTIpLA0KICAgICAgICBwbG90LmNhcHRpb24gPSBlbGVtZW50X3RleHQoZmFjZSA9ICJwbGFpbiIsIGZhbWlseSA9ICJzZXJpZiIsIHNpemUgPSA5KSkgKw0KICAjIHNjYWxlX2NvbG9yX3RhYmxlYXUocGFsZXR0ZSA9ICJUYWJsZWF1IDIwIikgKw0KICANCiAgZmFjZXRfd3JhcCh+Q2FzZXNfdHlwZSkgKw0KICBsYWJzKHRpdGxlID0gIlRvcCA1IENvdW50cmllcyBmb3IgYWxsIHR5cGUgb2YgRGFpbHkgY2FzZXMiLA0KICAgICAgIHN1YnRpdGxlID0gIkZvciBMYXRlc3QgNyBkYXlzIHNlcGFyYXRlZCBieSBDYXNlcyBUeXBlIiwNCiAgICAgICBjYXB0aW9uID0gImNyZWF0ZWQgYnkgVmlTYSAoU2NpQXJ0ISEpIikgKw0KICBjb29yZF9jYXJ0ZXNpYW4oY2xpcCA9ICJvZmYiKQ0KYGBgDQoNCiMjIFRvcDUgQmFycGxvdHMgb2YgQ2FzZXMgey50YWJzZXQgLnRhYnNldC1mYWRlIC50YWJzZXQtcGlsbHN9DQoNCiMjIyArQmFycGx0IChEYWlseV9jYXNlcykNCg0KYGBge3IgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9Nn0NCg0KZGZfc3RhY2sgJT4lIA0KICBmaWx0ZXIoQ2FzZXNfdHlwZSA9PSAiRGFpbHlfY2FzZXMiLA0KICAgICAgICAgRGF0ZSA+IChtYXgoRGF0ZSwgbmEucm0gPSBUUlVFKSAtIDgpICYgRGF0ZSA8IG1heChEYXRlLCBuYS5ybSA9IFRSVUUpKSAlPiUgDQogIGdyb3VwX2J5KENvdW50cnkuUmVnaW9uLCBEYXRlLCBDYXNlc190eXBlKSAlPiUgDQogIHN1bW1hcmlzZShDYXNlc19jb3VudCA9IHN1bShDYXNlc19jb3VudCkpICU+JQ0KICBncm91cF9ieShEYXRlLCBDYXNlc190eXBlKSAlPiUgDQogIHNsaWNlX21heChvcmRlcl9ieSA9IENhc2VzX2NvdW50LCBuID0gNSkgJT4lIA0KICBtdXRhdGUoQ2FzZXNfc2l6ZSA9IENhc2VzX2NvdW50IC8gc3VtKENhc2VzX2NvdW50KSkgJT4lIA0KICB1bmdyb3VwKCkgJT4lIA0KICANCiAgbXV0YXRlKENvdW50cnkuUmVnaW9uID0gZmN0X3Jlb3JkZXIoQ291bnRyeS5SZWdpb24sIENhc2VzX2NvdW50LCBtYXgpKSAlPiUgDQogIA0KICBnZ3Bsb3QoYWVzKHggPSBDYXNlc19jb3VudCwgeSA9IENvdW50cnkuUmVnaW9uKSkgKw0KICBnZW9tX2NvbChhZXMoZmlsbCA9IENvdW50cnkuUmVnaW9uKSkgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSwNCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLA0KICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAicGxhaW4iLCBmYW1pbHkgPSAic2VyaWYiLCBzaXplID0gMTQpLA0KICAgICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAicGxhaW4iLCBmYW1pbHkgPSAic2VyaWYiLCBzaXplID0gOSkpICsNCiAgc2NhbGVfZmlsbF90YWJsZWF1KHBhbGV0dGUgPSAiVGFibGVhdSAyMCIpICsNCiAgc2NhbGVfeF9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6dW5pdF9mb3JtYXQoc2NhbGUgPSAxZS0zLCB1bml0ID0gImsiKSkgKw0KICANCiAgZmFjZXRfd3JhcCh+RGF0ZSkgKw0KICBsYWJzKHRpdGxlID0gIlRvcCA1IENvdW50cmllcyBieSBEYWlseSBjYXNlcyIsDQogICAgICAgc3VidGl0bGUgPSAiRm9yIExhdGVzdCA3IGRheXMgc2VwYXJhdGVkIGJ5IERhdGVzIiwNCiAgICAgICBjYXB0aW9uID0gImNyZWF0ZWQgYnkgVmlTYSAoU2NpQXJ0ISEpIiwNCiAgICAgICB4ID0gIkRhaWx5IENhc2VzIGNvdW50IiwNCiAgICAgICB5ID0gIiIpICsNCiAgY29vcmRfY2FydGVzaWFuKGNsaXAgPSAib2ZmIikNCmBgYA0KDQojIyMgK0JhcnBsdCAoRGFpbHlfcmVjb3ZlcmVkKQ0KDQpgYGB7ciBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD02fQ0KDQpkZl9zdGFjayAlPiUgDQogIGZpbHRlcihDYXNlc190eXBlID09ICJEYWlseV9yZWNvdmVyZWQiLA0KICAgICAgICAgRGF0ZSA+IChtYXgoRGF0ZSwgbmEucm0gPSBUUlVFKSAtIDgpICYgRGF0ZSA8IG1heChEYXRlLCBuYS5ybSA9IFRSVUUpKSAlPiUgDQogIGdyb3VwX2J5KENvdW50cnkuUmVnaW9uLCBEYXRlLCBDYXNlc190eXBlKSAlPiUgDQogIHN1bW1hcmlzZShDYXNlc19jb3VudCA9IHN1bShDYXNlc19jb3VudCkpICU+JQ0KICBncm91cF9ieShEYXRlLCBDYXNlc190eXBlKSAlPiUgDQogIHNsaWNlX21heChvcmRlcl9ieSA9IENhc2VzX2NvdW50LCBuID0gNSkgJT4lIA0KICBtdXRhdGUoQ2FzZXNfc2l6ZSA9IENhc2VzX2NvdW50IC8gc3VtKENhc2VzX2NvdW50KSkgJT4lIA0KICB1bmdyb3VwKCkgJT4lIA0KICANCiAgbXV0YXRlKENvdW50cnkuUmVnaW9uID0gZmN0X3Jlb3JkZXIoQ291bnRyeS5SZWdpb24sIENhc2VzX2NvdW50LCBtYXgpKSAlPiUgDQogIA0KICBnZ3Bsb3QoYWVzKHggPSBDYXNlc19jb3VudCwgeSA9IENvdW50cnkuUmVnaW9uKSkgKw0KICBnZW9tX2NvbChhZXMoZmlsbCA9IENvdW50cnkuUmVnaW9uKSkgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSwNCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLA0KICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAicGxhaW4iLCBmYW1pbHkgPSAic2VyaWYiLCBzaXplID0gMTQpLA0KICAgICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAicGxhaW4iLCBmYW1pbHkgPSAic2VyaWYiLCBzaXplID0gOSksDQogICAgICAgIHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChjb2xvdXIgPSAiYmxhY2siLCBzaXplID0gMSkgKSArDQogIHNjYWxlX2ZpbGxfdGFibGVhdShwYWxldHRlID0gIlRhYmxlYXUgMjAiKSArDQogIHNjYWxlX3hfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnVuaXRfZm9ybWF0KHNjYWxlID0gMWUtMywgdW5pdCA9ICJrIikpICsNCiAgDQogIGZhY2V0X3dyYXAofkRhdGUpICsNCiAgbGFicyh0aXRsZSA9ICJUb3AgNSBDb3VudHJpZXMgYnkgRGFpbHkgUmVjb3ZlcmVkIGNhc2VzIiwNCiAgICAgICBzdWJ0aXRsZSA9ICJGb3IgTGF0ZXN0IDcgZGF5cyBzZXBhcmF0ZWQgYnkgRGF0ZXMiLA0KICAgICAgIGNhcHRpb24gPSAiY3JlYXRlZCBieSBWaVNhIChTY2lBcnQhISkiLA0KICAgICAgIHggPSAiRGFpbHkgUmVjb3ZlcmVkIENhc2VzIGNvdW50IiwNCiAgICAgICB5ID0gIiIpICsNCiAgY29vcmRfY2FydGVzaWFuKGNsaXAgPSAib2ZmIikNCg0KYGBgDQoNCiMjIyArQmFycGx0IChEYWlseV9kZWF0aHMpDQoNCmBgYHtyIGZpZy53aWR0aD05LCBmaWcuaGVpZ2h0PTZ9DQoNCmRmX3N0YWNrICU+JSANCiAgZmlsdGVyKENhc2VzX3R5cGUgPT0gIkRhaWx5X2RlYXRocyIsDQogICAgICAgICBEYXRlID4gKG1heChEYXRlLCBuYS5ybSA9IFRSVUUpIC0gOCkgJiBEYXRlIDwgbWF4KERhdGUsIG5hLnJtID0gVFJVRSkpICU+JSANCiAgZ3JvdXBfYnkoQ291bnRyeS5SZWdpb24sIERhdGUsIENhc2VzX3R5cGUpICU+JSANCiAgc3VtbWFyaXNlKENhc2VzX2NvdW50ID0gc3VtKENhc2VzX2NvdW50KSkgJT4lDQogIGdyb3VwX2J5KERhdGUsIENhc2VzX3R5cGUpICU+JSANCiAgc2xpY2VfbWF4KG9yZGVyX2J5ID0gQ2FzZXNfY291bnQsIG4gPSA1KSAlPiUgDQogIG11dGF0ZShDYXNlc19zaXplID0gQ2FzZXNfY291bnQgLyBzdW0oQ2FzZXNfY291bnQpKSAlPiUgDQogIHVuZ3JvdXAoKSAlPiUgDQogIA0KICBtdXRhdGUoQ291bnRyeS5SZWdpb24gPSBmY3RfcmVvcmRlcihDb3VudHJ5LlJlZ2lvbiwgQ2FzZXNfY291bnQsIG1heCkpICU+JSANCiAgDQogIGdncGxvdChhZXMoeCA9IENhc2VzX2NvdW50LCB5ID0gQ291bnRyeS5SZWdpb24pKSArDQogIGdlb21fY29sKGFlcyhmaWxsID0gQ291bnRyeS5SZWdpb24pKSArDQogICMgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWVfY2xlYW4oKSArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApLA0KICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsDQogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJwbGFpbiIsIGZhbWlseSA9ICJzZXJpZiIsIHNpemUgPSAxNCksDQogICAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJwbGFpbiIsIGZhbWlseSA9ICJzZXJpZiIsIHNpemUgPSA5KSkgKw0KICBzY2FsZV9maWxsX3RhYmxlYXUocGFsZXR0ZSA9ICJUYWJsZWF1IDIwIikgKw0KICBzY2FsZV94X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjp1bml0X2Zvcm1hdChzY2FsZSA9IDFlLTMsIHVuaXQgPSAiayIpKSArDQogIA0KICBmYWNldF93cmFwKH5EYXRlKSArDQogIGxhYnModGl0bGUgPSAiVG9wIDUgQ291bnRyaWVzIGJ5IERhaWx5IERlYXRocyIsDQogICAgICAgc3VidGl0bGUgPSAiRm9yIExhdGVzdCA3IGRheXMiLA0KICAgICAgIGNhcHRpb24gPSAiY3JlYXRlZCBieSBWaVNhIChTY2lBcnQhISkiLA0KICAgICAgIHggPSAiRGFpbHkgRGVhdGggQ2FzZXMgY291bnQiLA0KICAgICAgIHkgPSAiIikgKw0KICBjb29yZF9jYXJ0ZXNpYW4oY2xpcCA9ICJvZmYiKQ0KDQpgYGANCg0KIyMjIHBsb3RseSArc3VidGl0bGUNCg0KYGBge3IgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9Nn0NCg0KZ2dwbG90bHkoZGZfc3RhY2sgJT4lIA0KICBmaWx0ZXIoQ2FzZXNfdHlwZSA9PSAiRGFpbHlfZGVhdGhzIiwNCiAgICAgICAgIERhdGUgPiAobWF4KERhdGUsIG5hLnJtID0gVFJVRSkgLSA4KSAmIERhdGUgPCBtYXgoRGF0ZSwgbmEucm0gPSBUUlVFKSkgJT4lIA0KICBncm91cF9ieShDb3VudHJ5LlJlZ2lvbiwgRGF0ZSwgQ2FzZXNfdHlwZSkgJT4lIA0KICBzdW1tYXJpc2UoQ2FzZXNfY291bnQgPSBzdW0oQ2FzZXNfY291bnQpKSAlPiUNCiAgZ3JvdXBfYnkoRGF0ZSwgQ2FzZXNfdHlwZSkgJT4lIA0KICBzbGljZV9tYXgob3JkZXJfYnkgPSBDYXNlc19jb3VudCwgbiA9IDUpICU+JSANCiAgbXV0YXRlKENhc2VzX3NpemUgPSBDYXNlc19jb3VudCAvIHN1bShDYXNlc19jb3VudCkpICU+JSANCiAgdW5ncm91cCgpICU+JSANCiAgDQogIG11dGF0ZShDb3VudHJ5LlJlZ2lvbiA9IGZjdF9yZW9yZGVyKENvdW50cnkuUmVnaW9uLCBDYXNlc19jb3VudCwgbWF4KSkgJT4lIA0KICANCiAgZ2dwbG90KGFlcyh4ID0gQ2FzZXNfY291bnQsIHkgPSBDb3VudHJ5LlJlZ2lvbikpICsNCiAgZ2VvbV9jb2woYWVzKGZpbGwgPSBDb3VudHJ5LlJlZ2lvbikpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCksDQogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwNCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gInBsYWluIiwgZmFtaWx5ID0gInNlcmlmIiwgc2l6ZSA9IDE0KSwNCiAgICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gInBsYWluIiwgZmFtaWx5ID0gInNlcmlmIiwgc2l6ZSA9IDkpKSArDQogIHNjYWxlX2ZpbGxfdGFibGVhdShwYWxldHRlID0gIlRhYmxlYXUgMjAiKSArDQogIHNjYWxlX3hfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnVuaXRfZm9ybWF0KHNjYWxlID0gMWUtMywgdW5pdCA9ICJrIikpICsNCiAgDQogIGZhY2V0X3dyYXAofkRhdGUpICsNCiAgbGFicyh0aXRsZSA9ICJUb3AgNSBDb3VudHJpZXMgb2YgRGFpbHkgRGVhdGhzIGNhc2VzIiwNCiAgICAgICBzdWJ0aXRsZSA9ICJGb3IgTGF0ZXN0IDcgZGF5cyBzZXBhcmF0ZWQgYnkgRGF0ZXMiLA0KICAgICAgIGNhcHRpb24gPSAiY3JlYXRlZCBieSBWaVNhIChTY2lBcnQhISkiLA0KICAgICAgIHggPSAiRGFpbHkgRGVhdGggQ2FzZXMgY291bnQiLA0KICAgICAgIHkgPSAiIikgKw0KICBjb29yZF9jYXJ0ZXNpYW4oY2xpcCA9ICJvZmYiKSANCikgJT4lDQogIGxheW91dCh0aXRsZSA9IGxpc3QodGV4dCA9IHBhc3RlMCgnVG9wIDUgQ291bnRyaWVzIG9mIERhaWx5IERlYXRocyBjYXNlcycsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnPGJyPicsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnPHN1cD4nLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ0ZvciBMYXRlc3QgNyBkYXlzIHNlcGFyYXRlZCBieSBEYXRlcycsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnPC9zdXA+JykpKQ0KYGBgDQoNCiMgQ2FzZXMgRGlzdHJpYnV0aW9uIGJ5IGNvbnRpbmVudCB7LnRhYnNldCAudGFic2V0LWZhZGUgLnRhYnNldC1waWxsc30NCg0KIyMgTGF0ZXN0IENvbmZpcm1lZCBDYXNlcw0KDQpgYGB7ciBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD02fQ0KZ3JvdXBlZF9jYXNlc19kZiAlPiUgDQogIGZpbHRlcihEYXRlID09IG1heChEYXRlLCBuYS5ybSA9IFRSVUUpIywNCiAgICAgICAgICMgQ29uZmlybWVkIDwgNTAwMDAwMA0KICAgICAgICAgKSAlPiUgDQogIA0KICBnZ3Bsb3QoYWVzKHggPSBjb250aW5lbnQsIHkgPSBsb2coQ29uZmlybWVkKSwgbGFiZWwgPSBDb3VudHJ5LlJlZ2lvbikpICsNCiAgZ2VvbV9qaXR0ZXIoc2l6ZSA9IDEuOCwgd2lkdGggPSAwLjM1LCBhZXMoc2hhcGUgPSBDRlJfbGV2ZWwsIGNvbG9yID0gQ0ZSX2xldmVsKSkgKw0KICBnZW9tX3Zpb2xpbihhbHBoYSA9IC41LCBjb2xvciA9ICdncmV5NTAnLCBkcmF3X3F1YW50aWxlcyA9IGMoLjI1LCAuNSwgLjc1KSkgKw0KICBsYWJzKHRpdGxlID0gIkxhdGVzdCBDb25maXJtZW5kIGNhc2VzIGFjcm9zcyBjb250aW5lbnRzIiwNCiAgICAgICBzdWJ0aXRsZSA9ICJDb2xvcmVkIGJ5IENGUiBzZXZlcml0eSBsZXZlbCIsDQogICAgICAgY2FwdGlvbiA9ICJjcmVhdGVkIGJ5IFZpU2EgKFNjaUFydCEhKSIpDQoNCmBgYA0KDQojIyArcGxvdGx5DQoNCmBgYHtyIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTZ9DQoNCmdncGxvdGx5KGdyb3VwZWRfY2FzZXNfZGYgJT4lIA0KICBmaWx0ZXIoRGF0ZSA9PSBtYXgoRGF0ZSwgbmEucm0gPSBUUlVFKSMsDQogICAgICAgICAjIENvbmZpcm1lZCA8IDUwMDAwMDANCiAgICAgICAgICkgJT4lIA0KICANCiAgZ2dwbG90KGFlcyh4ID0gY29udGluZW50LCB5ID0gbG9nKENvbmZpcm1lZCksIGxhYmVsID0gQ291bnRyeS5SZWdpb24pKSArDQogIGdlb21faml0dGVyKHNpemUgPSAxLjgsIHdpZHRoID0gMC4zNSwgYWVzKHNoYXBlID0gQ0ZSX2xldmVsLCBjb2xvciA9IENGUl9sZXZlbCkpICsNCiAgZ2VvbV92aW9saW4oYWxwaGEgPSAuNSwgY29sb3IgPSAnZ3JleTUwJywgZHJhd19xdWFudGlsZXMgPSBjKC4yNSwgLjUsIC43NSkpICsNCiAgbGFicyh0aXRsZSA9ICJMYXRlc3QgQ29uZmlybWVuZCBjYXNlcyBhY3Jvc3MgY29udGluZW50cyIsDQogICAgICAgc3VidGl0bGUgPSAiQ29sb3JlZCBieSBDRlIgc2V2ZXJpdHkgbGV2ZWwiLA0KICAgICAgIGNhcHRpb24gPSAiY3JlYXRlZCBieSBWaVNhIChTY2lBcnQhISkiKQ0KKQ0KYGBgDQoNCiMjIExhdGVzdCBBY3RpdmUgQ2FzZXMNCg0KYGBge3IgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9Nn0NCmdyb3VwZWRfY2FzZXNfZGYgJT4lIA0KICBmaWx0ZXIoRGF0ZSA9PSBtYXgoRGF0ZSwgbmEucm0gPSBUUlVFKSMsDQogICAgICAgICAjIEFjdGl2ZSA8IDUwMDAwMDANCiAgICAgICAgICkgJT4lIA0KICANCiAgZ2dwbG90KGFlcyh4ID0gY29udGluZW50LCB5ID0gbG9nKEFjdGl2ZSksIGxhYmVsID0gQ291bnRyeS5SZWdpb24pKSArDQogIGdlb21faml0dGVyKHNpemUgPSAxLjgsIHdpZHRoID0gMC4zNSwgYWVzKHNoYXBlID0gQ0ZSX2xldmVsLCBjb2xvciA9IENGUl9sZXZlbCkpICsNCiAgZ2VvbV92aW9saW4oYWxwaGEgPSAuNSwgY29sb3IgPSAnZ3JleTUwJywgZHJhd19xdWFudGlsZXMgPSBjKC4yNSwgLjUsIC43NSkpICsNCiAgbGFicyh0aXRsZSA9ICJMYXRlc3QgQWN0aXZlIGNhc2VzIGFjcm9zcyBjb250aW5lbnRzIiwNCiAgICAgICBzdWJ0aXRsZSA9ICJDb2xvcmVkIGJ5IENGUiBzZXZlcml0eSBsZXZlbCIsDQogICAgICAgY2FwdGlvbiA9ICJjcmVhdGVkIGJ5IFZpU2EgKFNjaUFydCEhKSIpDQoNCmBgYA0KDQojIyArcGxvdGx5IHRvb2x0aXANCg0KYGBge3IgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9Nn0NCg0KZ2dwbG90bHkoZ3JvdXBlZF9jYXNlc19kZiAlPiUgDQogIGZpbHRlcihEYXRlID09IG1heChEYXRlLCBuYS5ybSA9IFRSVUUpIywNCiAgICAgICAgICMgQWN0aXZlIDwgNTAwMDAwMA0KICAgICAgICAgKSAlPiUgDQogIA0KICBnZ3Bsb3QoYWVzKHggPSBjb250aW5lbnQsIHkgPSBsb2coQWN0aXZlKSwgbGFiZWwgPSBDb3VudHJ5LlJlZ2lvbikpICsNCiAgZ2VvbV9qaXR0ZXIoc2l6ZSA9IDEuOCwgd2lkdGggPSAwLjM1LCBhZXMoc2hhcGUgPSBDRlJfbGV2ZWwsIGNvbG9yID0gQ0ZSX2xldmVsKSkgKw0KICBnZW9tX3Zpb2xpbihhbHBoYSA9IC41LCBjb2xvciA9ICdncmV5NTAnLCBkcmF3X3F1YW50aWxlcyA9IGMoLjI1LCAuNSwgLjc1KSkgKw0KICBsYWJzKHRpdGxlID0gIkxhdGVzdCBBY3RpdmUgY2FzZXMgYWNyb3NzIGNvbnRpbmVudHMiLA0KICAgICAgIHN1YnRpdGxlID0gIkNvbG9yZWQgYnkgQ0ZSIHNldmVyaXR5IGxldmVsIiwNCiAgICAgICBjYXB0aW9uID0gImNyZWF0ZWQgYnkgVmlTYSAoU2NpQXJ0ISEpIikNCg0KICAsIHRvb2x0aXAgPSBjKCJsb2coQWN0aXZlKSIsICJjb250aW5lbnQiLCAibGFiZWwiKSkNCmBgYA0KDQojIyBnZ2ZvcmNlL2dlb21fc2luYQ0KDQpgYGB7ciBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD02fQ0KZ3JvdXBlZF9jYXNlc19kZiAlPiUgDQogIGZpbHRlcihEYXRlID09IG1heChEYXRlLCBuYS5ybSA9IFRSVUUpIywNCiAgICAgICAgICMgQWN0aXZlIDwgNTAwMDAwMA0KICAgICAgICAgKSAlPiUgDQogIA0KICBnZ3Bsb3QoYWVzKHggPSBjb250aW5lbnQsIHkgPSBsb2coQWN0aXZlKSwgbGFiZWwgPSBDb3VudHJ5LlJlZ2lvbikpICsNCiAgZ2VvbV92aW9saW4oYWxwaGEgPSAuNSwgY29sb3IgPSAnZ3JleTUwJywgZHJhd19xdWFudGlsZXMgPSBjKC4yNSwgLjUsIC43NSkpICsNCiAgZ2dmb3JjZTo6Z2VvbV9zaW5hKGFscGhhID0gLjcsIHNpemUgPSAxLjgsIHdpZHRoID0gMC4zNSwgYWVzKHNoYXBlID0gQ0ZSX2xldmVsLCBjb2xvciA9IENGUl9sZXZlbCkpICsNCiAgIyBnZW9tX2ppdHRlcigpICsNCiAgbGFicyh0aXRsZSA9ICJMYXRlc3QgQWN0aXZlIGNhc2VzIGFjcm9zcyBjb250aW5lbnRzIiwNCiAgICAgICBzdWJ0aXRsZSA9ICJDb2xvcmVkIGJ5IENGUiBzZXZlcml0eSBsZXZlbCIsDQogICAgICAgY2FwdGlvbiA9ICJjcmVhdGVkIGJ5IFZpU2EgKFNjaUFydCEhKSIpDQpgYGANCg0KIyMgK3Bsb3RseQ0KDQpgYGB7ciBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD02fQ0KZ2dwbG90bHkoZ3JvdXBlZF9jYXNlc19kZiAlPiUgDQogIGZpbHRlcihEYXRlID09IG1heChEYXRlLCBuYS5ybSA9IFRSVUUpIywNCiAgICAgICAgICMgQWN0aXZlIDwgNTAwMDAwMA0KICAgICAgICAgKSAlPiUgDQogIA0KICBnZ3Bsb3QoYWVzKHggPSBjb250aW5lbnQsIHkgPSBsb2coQWN0aXZlKSwgbGFiZWwgPSBDb3VudHJ5LlJlZ2lvbikpICsNCiAgZ2VvbV92aW9saW4oYWxwaGEgPSAuNSwgY29sb3IgPSAnZ3JleTUwJywgZHJhd19xdWFudGlsZXMgPSBjKC4yNSwgLjUsIC43NSkpICsNCiAgZ2dmb3JjZTo6Z2VvbV9zaW5hKHNpemUgPSAxLjgsIHdpZHRoID0gMC4zNSwgYWVzKHNoYXBlID0gQ0ZSX2xldmVsLCBjb2xvciA9IENGUl9sZXZlbCkpICsNCiAgIyBnZW9tX2ppdHRlcigpICsNCiAgDQogIGxhYnModGl0bGUgPSAiTGF0ZXN0IEFjdGl2ZSBjYXNlcyBhY3Jvc3MgY29udGluZW50cyIsDQogICAgICAgc3VidGl0bGUgPSAiQ29sb3JlZCBieSBDRlIgc2V2ZXJpdHkgbGV2ZWwiLA0KICAgICAgIGNhcHRpb24gPSAiY3JlYXRlZCBieSBWaVNhIChTY2lBcnQhISkiKQ0KICANCiAgLCB0b29sdGlwID0gYygibG9nKEFjdGl2ZSkiLCAiY29udGluZW50IiwgImxhYmVsIikpDQpgYGANCg==